看来NHibernate不能在实体中自动映射多个给定类型的IList。

考虑以下两个实体(基于Fluent NHibernate源代码附带的Examples.FirstProject示例代码)。

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

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

这似乎是一个非常有效的对象模型-每个商店都有数名员工和数名经理员工。

但是,当我自动映射时,“职员”和“经理”列表存储在Employee表中,并且所有表都具有相同的外键。
Employee Table

Id FirstName LastName Store_id
3  Daisy     Harrison   1
4  Jack      Torrance   1
5  Sue       Walkters   1
6  Tom       Tommorow   1
7  Dick      Diggler    1

最终结果是,当从数据库中读回数据时,表中的每个行都将填充到Staff和Managers列表中。

对我来说,这看起来像是“自动映射”中的错误,但是对于NHibernate来说,我还是任何形式的新手,而且还不完全了解它的局限性。

无论如何,我如何使NHibernate将两个列表视为不同的?

如果可能的话,我希望您有一个自动映射代码片段,该片段直接解决了我提供的示例代码(例如,类似“在CreateSessionFactory的.Mappings部分中放置此完全替代”之类的东西)。

这是因为我只对Automapping有点熟悉,而对旧的做事方式却一点也不熟悉,这意味着我还不能很好地“填补空白”。

但是,如果您只有时间向我指出正确的方向,那也将有所帮助。

这是我的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;
    }

最佳答案

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

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

请注意(至少在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);
    }


}

这是商店的映射替代:
// 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)");
   }
}

关于nhibernate - 如何在实体中将Fluent NHibernate Automapping与多个相同类型的列表一起使用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1773239/

10-17 02:33