如何将Fluent NHibernate自动映射用于实体中相同类型的多个列表?

如何将Fluent NHibernate自动映射用于实体中相同类型的多个列表?,nhibernate,fluent-nhibernate,nhibernate-mapping,automapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,Automapping,NHibernate似乎无法自动映射实体中给定类型的多个IList 考虑以下两个实体(基于Fluent NHibernate源代码中包含的Examples.FirstProject示例代码) 最终的结果是,当数据从数据库中读回时,员工和经理列表都会填充表中的每一行 对我来说,这看起来像是自动映射中的一个bug,但我对任何形式的NHibernate都是相当陌生的,还不完全知道它的局限性 在任何情况下,如何使NHibernate将这两个列表视为不同的? 如果可能的话,我希望能提供一个自动映射代码片段

NHibernate似乎无法自动映射实体中给定类型的多个IList

考虑以下两个实体(基于Fluent NHibernate源代码中包含的Examples.FirstProject示例代码)

最终的结果是,当数据从数据库中读回时,员工和经理列表都会填充表中的每一行

对我来说,这看起来像是自动映射中的一个bug,但我对任何形式的NHibernate都是相当陌生的,还不完全知道它的局限性

在任何情况下,如何使NHibernate将这两个列表视为不同的?

如果可能的话,我希望能提供一个自动映射代码片段,直接处理我提供的示例代码(例如,类似“在CreateSessionFactory的.Mappings部分中放置这个精确的覆盖”)

这是因为我只对自动映射有点熟悉,而对旧的处理方式一点也不熟悉,这意味着我还不能很好地“填补空白”

但是如果你有时间给我指出正确的方向,那也会很有帮助

以下是我的CreateSessionFactory代码,以提供一些上下文:

    private static ISessionFactory CreateSessionFactory()
    {
        ISessionFactory sessionFactory = null;

        const string autoMapExportDir = "AutoMapExport";
        if( !Directory.Exists(autoMapExportDir) )
            Directory.CreateDirectory(autoMapExportDir);

        try
        {
            var autoPersistenceModel = 
                AutoMap.AssemblyOf<Product>()
                        .Where(t => t.Namespace == "Examples.FirstProject.Entities")
                        .Conventions.Add( DefaultCascade.All() )
                ;

            sessionFactory = Fluently.Configure()
                .Database(SQLiteConfiguration.Standard
                              .UsingFile(DbFile)
                              .ShowSql()
                         )
                .Mappings(m => m.AutoMappings.Add(autoPersistenceModel)
                                             .ExportTo(autoMapExportDir)
                         )
                .ExposeConfiguration(BuildSchema)
                .BuildSessionFactory()
                ;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }

        return sessionFactory;
    }
私有静态ISessionFactory CreateSessionFactory()
{
ISessionFactory sessionFactory=null;
常量字符串automaexportdir=“automaexport”;
如果(!Directory.Exists(autoMapExportDir))
CreateDirectory(autoMapExportDir);
尝试
{
var autoPersistenceModel=
自动映射
.Where(t=>t.Namespace==“Examples.FirstProject.Entities”)
.Conventions.Add(DefaultCascade.All())
;
sessionFactory=fluntly.Configure()
.Database(SQLiteConfiguration.Standard
.UsingFile(DbFile)
.ShowSql()
)
.Mappings(m=>m.AutoMappings.Add(autoPersistenceModel)
.ExportTo(自动出口目录)
)
.ExposeConfiguration(构建架构)
.BuildSessionFactory()
;
}
捕获(例外e)
{
控制台写入线(e);
}
返回工厂;
}

Paul Batum回答了我的问题,并提供了一个独立的工作示例(在导航到链接页面后单击下载按钮)

下面的代码是从他的答案中复制出来的。关键点在清单末尾的StoreMap类中,该类使用Where子句设置覆盖,该子句使用Employee中的IsManager属性

请注意(至少在v.1.0.0.594中)有一个关于自动映射的大问题-映射类(例如StoreMap)不能与域类(例如Store)位于同一命名空间中

否则,NHibernate将抛出“NHibernate.MappingException: (XmlDocument)(2,4):XML验证错误:…”,带有 绝对没有迹象表明真正的问题是什么或在哪里

这可能是Fluent NHibernate更高版本中修复的错误

public class Employee 
{ 
    public virtual int Id { get; private set; } 
    public virtual string FirstName { get; set; } 
    public virtual string LastName { get; set; } 
    public virtual bool IsManager { get; set; } 
} 


public class Store 
{ 
    public virtual int Id { get; private set; } 
    public virtual IList<Employee> Staff { get; private set; } 
    public virtual IList<Employee> Managers { get; private set; } 


    public Store() 
    { 
        Staff = new List<Employee>(); 
        Managers = new List<Employee>(); 
    } 


    public void AddManager(Employee employee) 
    { 
        employee.IsManager = true; 
        this.Managers.Add(employee); 
    } 


    public void AddStaff(Employee employee) 
    { 
        this.Staff.Add(employee); 
    } 


} 
公共类员工
{ 
公共虚拟整数Id{get;private set;}
公共虚拟字符串FirstName{get;set;}
公共虚拟字符串LastName{get;set;}
公共虚拟bool IsManager{get;set;}
} 
公共类商店
{ 
公共虚拟整数Id{get;private set;}
公共虚拟IList Staff{get;private set;}
公共虚拟IList管理器{get;private set;}
公共商店()
{ 
职员=新名单();
经理=新列表();
} 
公共部门经理(员工)
{ 
employee.IsManager=true;
this.Managers.Add(employee);
} 
公共人员(员工)
{ 
this.Staff.Add(employee);
} 
} 
以下是存储的映射覆盖:

// Must be in different Namespace from class Store!!!
public class StoreMap : IAutoMappingOverride<Store> 
{ 
   public void Override(AutoMapping<Store> mapping) 
   { 
       mapping.HasMany(x => x.Managers) 
           .Cascade.All() 
           .Where("(IsManager = 1)"); 
       mapping.HasMany(x => x.Staff) 
           .Cascade.All() 
           .Where("(IsManager = 0)"); 
   } 
} 
//必须与类存储位于不同的命名空间中!!!
公共类StoreMap:IAutoMappingOverride
{ 
公共无效替代(自动映射)
{ 
mapping.HasMany(x=>x.Managers)
.Cascade.All()
。其中(“(IsManager=1)”;
mapping.HasMany(x=>x.Staff)
.Cascade.All()
。其中(“(IsManager=0)”;
} 
} 
public class Employee 
{ 
    public virtual int Id { get; private set; } 
    public virtual string FirstName { get; set; } 
    public virtual string LastName { get; set; } 
    public virtual bool IsManager { get; set; } 
} 


public class Store 
{ 
    public virtual int Id { get; private set; } 
    public virtual IList<Employee> Staff { get; private set; } 
    public virtual IList<Employee> Managers { get; private set; } 


    public Store() 
    { 
        Staff = new List<Employee>(); 
        Managers = new List<Employee>(); 
    } 


    public void AddManager(Employee employee) 
    { 
        employee.IsManager = true; 
        this.Managers.Add(employee); 
    } 


    public void AddStaff(Employee employee) 
    { 
        this.Staff.Add(employee); 
    } 


} 
// Must be in different Namespace from class Store!!!
public class StoreMap : IAutoMappingOverride<Store> 
{ 
   public void Override(AutoMapping<Store> mapping) 
   { 
       mapping.HasMany(x => x.Managers) 
           .Cascade.All() 
           .Where("(IsManager = 1)"); 
       mapping.HasMany(x => x.Staff) 
           .Cascade.All() 
           .Where("(IsManager = 0)"); 
   } 
}