Fluent NHibernate DuplicateMappingException with A

2019-02-10 15:57发布

Summary:

I want to save two classes of the same name and different namespaces with the Fluent NHibernate Automapper

Context

I'm writing having to import a lot of different objects to database for testing. I'll eventually write mappers to a proper model.

I've been using code gen and Fluent NHibernate to take these DTOs and dump them straight to db.

the exception does say to (try using auto-import="false")

Code

public class ClassConvention : IClassConvention
{
    public void Apply(IClassInstance instance)
    {
        instance.Table(instance.EntityType.Namespace.Replace(".", "_"));
    }
}

namespace Sample.Models.Test1
{
    public class Test
    {
        public virtual int Id { get; set; }
        public virtual string Something { get; set; }
    }
}

namespace Sample.Models.Test2
{
    public class Test
    {
        public virtual int Id { get; set; }
        public virtual string SomethingElse { get; set; }        
    }
}

And here's the actual app code

            var model = AutoMap.AssemblyOf<Service1>()
                .Where(t => t.Namespace.StartsWith("Sample.Models"))
                .Conventions.AddFromAssemblyOf<Service1>();
            var cfg = Fluently.Configure()
                .Database(
                MySQLConfiguration.Standard.ConnectionString(
                    c => c.Is("database=test;server=localhost;user id=root;Password=;")))
                .Mappings(m => m.AutoMappings.Add(model))
                .BuildConfiguration();
            new SchemaExport(cfg).Execute(false, true, false);

Thanks I really appreciate any help

Update using Fluent Nhibernate RC1

6条回答
The star\"
2楼-- · 2019-02-10 16:07

solution from fluent-nhibernate forums by James Gregory

Got around to having a proper look at this tonight. Basically, it is down to the AutoImport stuff the exception mentioned; when NHibernate is given the first mapping it sees that the entity is named with the full assembly qualified name and creates an import for the short name (being helpful!), and then when you add the second one it then complains that this import is now going to conflict. So the solution is to turn off the auto importing; unfortunately, we don't have a way to do that in the RC... I've just commited a fix that adds in the ability to change this in a convention. So if you get the latest binaries or source, you should be able to change your Conventions line in your attached project to do this:

.Conventions.Setup(x =>  {   
  x.AddFromAssemblyOf<Program>();   
  x.Add(AutoImport.Never());  }); 

Which adds all the conventions you've defined in your assembly, then uses one of the helper conventions to turn off auto importing.

查看更多
萌系小妹纸
3楼-- · 2019-02-10 16:07

Use the BeforeBindMapping event to gain access to the object representation of the .HBM XML files.

This event allows you to modify any properties at runtime before the NHibernate Session Factory is created. This also makes the FluentNHibernate-equivalent convention unnecessary. Unfortunately there is currently no official documentation around this really great feature.

Here's a global solution to duplicate mapping problems ( Just remember that all HQL queries will now need to use Fully Qualified Type names instead of just the class names ).

var configuration = new NHibernate.Cfg.Configuration();

configuration.BeforeBindMapping += (sender, args) => args.Mapping.autoimport = false;
查看更多
做个烂人
4楼-- · 2019-02-10 16:10

I was not able to get this to work using Conventions for FluentMappings (in contrast to AutoMappings). However, the following works for me, though it must be added to each ClassMap where needed.

public class AMap : ClassMap<A> 
{
    public AMap()
    {
        HibernateMapping.Not.AutoImport();
        Map(x => x.Item, "item");
        ...
    }
}
查看更多
Explosion°爆炸
5楼-- · 2019-02-10 16:11

I am having real problem with this, and the example above or any of its variants do not help.

var cfg = new NotifyFluentNhibernateConfiguration();

    return Fluently.Configure()
      .Database(
       FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005
            .ConnectionString("Server=10.2.65.227\\SOSDBSERVER;Database=NotifyTest;User ID=NHibernateTester;Password=test;Trusted_Connection=False;")
      )

      .Mappings(m => {
          m.AutoMappings
            .Add(AutoMap.AssemblyOf<SubscriptionManagerRP>(cfg));
          m.FluentMappings.Conventions.Setup(x =>
          {
              x.AddFromAssemblyOf<Program>();
              x.Add(AutoImport.Never());
          });
      } )

      .BuildSessionFactory();

I can't find Program's reference..

I've also tried to put down a seperate xml file to in desperation config fluent nhibernate's mapping to auto-import = false with no success.

Can I please have some more extensive example on how to do this?

Edit, I got the latest trunk just weeks ago.

Edit, Solved this by removing all duplicates.

查看更多
看我几分像从前
6楼-- · 2019-02-10 16:12

I have had the same problem. I solved it like this:

Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2008
            .ConnectionString(...)
            .AdoNetBatchSize(500))
        .Mappings(m => m.FluentMappings
            .Conventions.Setup(x => x.Add(AutoImport.Never()))
            .AddFromAssembly(...)
            .AddFromAssembly(...)
            .AddFromAssembly(...)
            .AddFromAssembly(...))
        ;

The imported part is: .Conventions.Setup(x => x.Add(AutoImport.Never())). Everything seems to be working fine with this configuration.

查看更多
倾城 Initia
7楼-- · 2019-02-10 16:26

I had to play around with where to add the convention AutoImport.Never() to. I have my persistence mapping separated into different projects - models for each application can also be found in different projects. Using it with Fluent NHibernate and auto mapping.

There are occasions when domains, well mappings really have to be combined. This would be when I need access to all domains. POCO classes used will sometimes have the same name and different namespaces, just as examples above.

Here is how my combine all mapping looks like:

internal static class NHIbernateUtility
{
    public static ISessionFactory CreateSessionFactory(string connectionString)
    {
        return Fluently.Configure()
            .Database(
                MsSqlConfiguration
                    .MsSql2008
                    .ConnectionString(connectionString))
            .Mappings(m => m.AutoMappings
                .Add(ProjectA.NHibernate.PersistenceMapper.CreatePersistenceModel()))
            .Mappings(m => m.AutoMappings
                .Add(ProjectB.NHibernate.PersistenceMapper.CreatePersistenceModel()))
            .Mappings(m => m.AutoMappings
                .Add(ProjectC.NHibernate.PersistenceMapper.CreatePersistenceModel())).BuildSessionFactory();
    }
}

And one of the persistence mappers:

public static class PersistenceMapper
{
    public static AutoPersistenceModel CreatePersistenceModel()
    {
        return
            AutoMap.AssemblyOf<Credential>(new AutoMapConfiguration())
                .IgnoreBase<BaseEntity>()
                .Conventions.Add(AutoImport.Never())
                .Conventions.Add<TableNameConvention>()
                .Conventions.Add<StandardForeignKeyConvention>()
                .Conventions.Add<CascadeAllConvention>()
                .Conventions.Add<StandardManyToManyTableNameConvention>()
                .Conventions.Add<PropertyConvention>();
    }
}

Persistence mappers are very similar for each POCO namespace - some have overrides. I had to add .Conventions.Add(AutoImport.Never()) to each persistence mapper and it works like a charm.

Just wanted to share this if anyone else is doing it this way.

查看更多
登录 后发表回答