代码之家  ›  专栏  ›  技术社区  ›  Tom Bushell

如何在一个实体中使用具有相同类型的多个列表的Fluent NHibernate自动应用程序?

  •  6
  • Tom Bushell  · 技术社区  · 15 年前

    似乎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 
    

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

    对我来说,这看起来像是自动应用程序中的一个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;
        }
    
    1 回复  |  直到 15 年前
        1
  •  5
  •   Tom Bushell    15 年前

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

    以下代码是从他的答案中复制的。关键点在列表末尾的storemap类中,该类通过在Employee中使用isManager属性的where子句设置覆盖。

    注意(至少在1.0.0.594版本中)有一个自动应用的大gotcha- 映射类(例如storemap)不能与域类(例如store)在同一命名空间中!

    否则,NHibernate会抛出 “nhibernate.mappingeexception: (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)"); 
       } 
    }