如何将Fluent NHibernate自动映射用于实体中相同类型的多个列表?
NHibernate似乎无法自动映射实体中给定类型的多个IList 考虑以下两个实体(基于Fluent NHibernate源代码中包含的Examples.FirstProject示例代码) 最终的结果是,当数据从数据库中读回时,员工和经理列表都会填充表中的每一行 对我来说,这看起来像是自动映射中的一个bug,但我对任何形式的NHibernate都是相当陌生的,还不完全知道它的局限性 在任何情况下,如何使NHibernate将这两个列表视为不同的? 如果可能的话,我希望能提供一个自动映射代码片段,直接处理我提供的示例代码(例如,类似“在CreateSessionFactory的.Mappings部分中放置这个精确的覆盖”) 这是因为我只对自动映射有点熟悉,而对旧的处理方式一点也不熟悉,这意味着我还不能很好地“填补空白” 但是如果你有时间给我指出正确的方向,那也会很有帮助 以下是我的CreateSessionFactory代码,以提供一些上下文:如何将Fluent NHibernate自动映射用于实体中相同类型的多个列表?,nhibernate,fluent-nhibernate,nhibernate-mapping,automapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,Automapping,NHibernate似乎无法自动映射实体中给定类型的多个IList 考虑以下两个实体(基于Fluent NHibernate源代码中包含的Examples.FirstProject示例代码) 最终的结果是,当数据从数据库中读回时,员工和经理列表都会填充表中的每一行 对我来说,这看起来像是自动映射中的一个bug,但我对任何形式的NHibernate都是相当陌生的,还不完全知道它的局限性 在任何情况下,如何使NHibernate将这两个列表视为不同的? 如果可能的话,我希望能提供一个自动映射代码片段
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)");
}
}