查询时 NHibernate HasMany List 保持为空

Posted

技术标签:

【中文标题】查询时 NHibernate HasMany List 保持为空【英文标题】:NHibernate HasMany List remains empty when querying 【发布时间】:2013-05-23 08:58:48 【问题描述】:

我遇到了一个奇怪的问题:每当我查询具有 IList 的实体时,它仍然是空的。可以查询语言实体本身...这与我的复合键有关吗?

NHProf 显示 BOTH 实体都被 sql 查询了,但是由于某种原因,结果没有链接:-/

这里有一些代码:

public class Employee : User

    public virtual string firstname  get; set; 
    public virtual string lastname  get; set; 
    public virtual string uid  get; set; 
    public virtual string identity_provider
    public virtual IList<Language> languages  get; set; 

对应的映射:

public class EmployeeMap : ClassMap<Employee>

    public EmployeeMap()
    
        Table("employee");
        Not.LazyLoad();
        CompositeId()
            .KeyProperty(x => x.uid)
            .KeyProperty(x => x.identity_provider);
        Map(x => x.firstname);
        Map(x => x.lastname);

        HasMany<Language>(x => x.languages)
            .Table("employee_spoken_language")
            .KeyColumns.Add("employee_uid","employee_identity_provider")
            .Inverse().Cascade.All();
    

为了完整起见,这就是“语言”的映射方式:

public class LanguageMap : ClassMap<SpokenLanguage>

    public LanguageMap()
    
        Table("employee_spoken_language");
        Not.LazyLoad();
        CompositeId()
            .KeyProperty(x => x.employee_uid)
            .KeyProperty(x => x.employee_identity_provider)
            .KeyProperty(x => x.name);
        References(x => x.knowledge_level).Column("knowledge_level");
    

无论我更改什么,我的员工实体总是显示language = !?这真的让我发疯,我找不到错误。我确保执行查询语言的 sql!我确保数据在数据库中。而且因为我使用的是fluent,所以我还检查了创建的hmb:

<bag cascade="all" inverse="true" name="languages" table="employee_spoken_language">
  <key>
    <column name="employee_uid" />
    <column name="employee_identity_provider" />
  </key>
  <one-to-many class="Jobportal.Language, wcf, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

希望有人能对此有所启发...提前致谢!

问候, 马丁

【问题讨论】:

好的...现场测试:我重新创建了两个类并将仅 uid 设置为 id。相同的映射...有效。如果我重新应用复合键,它会按照描述失败。很奇怪... :-/ Martin 在我的回答中为你做了映射 【参考方案1】:

这是一个有趣的项目,我在所有项目中都使用 nHibernate,但很少使用复合键。我曾经手动完成所有映射(学习),但现在我使用 Entity Developer 工具来生成它们。我在我的数据库中创建了与您的结构相同的可比较的 Employee 和 Language 表,并在它们上运行 Entity Developer 以为您生成流畅的映射。我在下面列出了这些。我没有看到任何巨大的差异,但知道 nHibernate 有多么挑剔可能值得一试。我可能有一些属性长度错误等,但会根据您的特定需求进行调整。

对于员工:

public class EmployeeMap : ClassMap<Employee>

    public EmployeeMap()
    
          Schema(@"dbo");
          Table(@"Employees");
          LazyLoad();
          CompositeId()
            .KeyProperty(x => x.Uid, set => 
                set.Type("String");
                set.ColumnName("uid");
                set.Length(50);
                set.Access.Property();  )
            .KeyProperty(x => x.IdentityProvider, set => 
                set.Type("String");
                set.ColumnName("identity_provider");
                set.Length(50);
                set.Access.Property();  );
          Map(x => x.Firstname)    
            .Column("firstname")
            .CustomType("String")
            .Access.Property()
            .Generated.Never()
            .CustomSqlType("varchar")
            .Not.Nullable();
          Map(x => x.Lastname)    
            .Column("lastname")
            .CustomType("String")
            .Access.Property()
            .Generated.Never()
            .CustomSqlType("varchar")
            .Not.Nullable();
          HasMany<Language>(x => x.Languages)
            .Access.Property()
            .AsSet()
            .Cascade.None()
            .LazyLoad()
            .Inverse()
            .Generic()
            .KeyColumns.Add("uid", mapping => mapping.Name("uid")
                                                                 .SqlType("varchar")
                                                                 .Not.Nullable()
                                                                 .Length(50))
            .KeyColumns.Add("identity_provider", mapping => mapping.Name("identity_provider")
                                                                 .SqlType("varchar")
                                                                 .Not.Nullable()
                                                                 .Length(50));
    

语言:

public class LanguageMap : ClassMap<Language>

   public LanguageMap()
    
          Schema(@"dbo");
          Table(@"Languages");
          LazyLoad();
          CompositeId()
            .KeyProperty(x => x.Uid, set => 
                set.Type("String");
                set.ColumnName("uid");
                set.Length(50);
                set.Access.Property();  )
            .KeyProperty(x => x.IdentityProvider, set => 
                set.Type("String");
                set.ColumnName("identity_provider");
                set.Length(50);
                set.Access.Property();  )
            .KeyProperty(x => x.Name, set => 
                set.Type("String");
                set.ColumnName("name");
                set.Length(50);
                set.Access.Property();  );
          References(x => x.Employee)
            .Class<Employee>()
            .Access.Property()
            .Cascade.None()
            .LazyLoad()
            .Columns("uid", "identity_provider");
    

如果这些工作更好,请告诉我,如果没有,我会生成一些测试数据并尝试使用映射对这些表运行一些查询。

要考虑的另一件事是确保您使用的是最新版本的 nHibernate。

【讨论】:

嘿!感谢您的提示。由于我在这个项目中的时间不多了,我将 uid 和身份提供者连接起来以将其用作单个字段并避免 90% 的复合键。但是,一旦我“在安全方面”,我会尝试你的方法并在这里发布反馈。可能需要几个星期。问候,

以上是关于查询时 NHibernate HasMany List 保持为空的主要内容,如果未能解决你的问题,请参考以下文章

流畅的 NHibernate HASMANY 映射,无需参考

使用 Fluent NHibernate 和 AsList() 时指定主键

如何在Fluent NHibernate中映射受保护的集合?

NHibernate:查询未映射实体时的意外行为

单向一对多关系的流畅 NHibernate 配置 - 删除问题

流利的NHibernate显示不使用给定的属性名称