Join 从数据库中获取具有连接实体的整个实体并避免延迟加载,nHibernate QueryOver
我有这样一个实体:Join 从数据库中获取具有连接实体的整个实体并避免延迟加载,nHibernate QueryOver,join,fluent-nhibernate,queryover,Join,Fluent Nhibernate,Queryover,我有这样一个实体: public class Employment { public virtual Company Company {get; set;} public virtual Person Person {get; set;} public virtual string Description {get; set;} } SELECT e.Description, c.A, c.B, c.C, p.D, p.E, p.F FROM Employment e
public class Employment
{
public virtual Company Company {get; set;}
public virtual Person Person {get; set;}
public virtual string Description {get; set;}
}
SELECT e.Description, c.A, c.B, c.C, p.D, p.E, p.F
FROM Employment e
JOIN Company c ON e.Company_Id = c.Company_Id
JOIN Person p ON e.Person_Id = p.Person_Id;
//This works, but the objects are retrieved as PersonProxy and CompanyProxy,
//generating 2 SELECT statements for each Employment I map to EmploymentDto
var queryOver =
session.QueryOver<Employment>()
.Fetch(x => x.Person).Eager
.Fetch(x => x.Company).Eager
var mapResult = MappingEngine.Map<IList<EmploymentDto>>(queryOver.List());
//This works, but the objects are still retrieved as PersonProxy and CompanyProxy,
var queryOver =
session.QueryOver<Employment>()
.JoinAlias(x => x.Person, () => personAlias, JoinType.InnerJoin)
.JoinAlias(x => x.Company, () => companyAlias, JoinType.InnerJoin);
var mapResult = MappingEngine.Map<IList<EmploymentDto>>(queryOver.List());
提供其他两个实体之间的关系。他们有相应的DTO,我想返回一个结果集,其中包含个人和公司的所有信息。查询是在Employment表上执行的,我的问题是Hibernate为每个公司和每个人生成一条select语句
在我的数据库中,就业表有1000行。Nhibernate生成2001 select语句,当我将它们映射到DTO时,一个用于就业列表,另一个用于每个人和公司
我希望hibernate一次获取所有信息,在SQL中,我会这样做:
public class Employment
{
public virtual Company Company {get; set;}
public virtual Person Person {get; set;}
public virtual string Description {get; set;}
}
SELECT e.Description, c.A, c.B, c.C, p.D, p.E, p.F
FROM Employment e
JOIN Company c ON e.Company_Id = c.Company_Id
JOIN Person p ON e.Person_Id = p.Person_Id;
//This works, but the objects are retrieved as PersonProxy and CompanyProxy,
//generating 2 SELECT statements for each Employment I map to EmploymentDto
var queryOver =
session.QueryOver<Employment>()
.Fetch(x => x.Person).Eager
.Fetch(x => x.Company).Eager
var mapResult = MappingEngine.Map<IList<EmploymentDto>>(queryOver.List());
//This works, but the objects are still retrieved as PersonProxy and CompanyProxy,
var queryOver =
session.QueryOver<Employment>()
.JoinAlias(x => x.Person, () => personAlias, JoinType.InnerJoin)
.JoinAlias(x => x.Company, () => companyAlias, JoinType.InnerJoin);
var mapResult = MappingEngine.Map<IList<EmploymentDto>>(queryOver.List());
甚至
SELECT Description FROM Employment;
SELECT c.A, c.B, c.C FROM Employment e
JOIN Company c ON e.Company_Id = c.Company_Id;
SELECT p.D, p.E, p.F FROM Employment e
JOIN Person p ON e.Person_Id = p.Person_Id;
我是nHibernate、QueryOver的新用户。我也欢迎Linq访问实体答案,但我更喜欢避免使用Linq查询表达式
我已经浏览了整个网络,阅读了JoinQuery、JoinAlias和Fetch的相关内容,并得出如下结论:
public class Employment
{
public virtual Company Company {get; set;}
public virtual Person Person {get; set;}
public virtual string Description {get; set;}
}
SELECT e.Description, c.A, c.B, c.C, p.D, p.E, p.F
FROM Employment e
JOIN Company c ON e.Company_Id = c.Company_Id
JOIN Person p ON e.Person_Id = p.Person_Id;
//This works, but the objects are retrieved as PersonProxy and CompanyProxy,
//generating 2 SELECT statements for each Employment I map to EmploymentDto
var queryOver =
session.QueryOver<Employment>()
.Fetch(x => x.Person).Eager
.Fetch(x => x.Company).Eager
var mapResult = MappingEngine.Map<IList<EmploymentDto>>(queryOver.List());
//This works, but the objects are still retrieved as PersonProxy and CompanyProxy,
var queryOver =
session.QueryOver<Employment>()
.JoinAlias(x => x.Person, () => personAlias, JoinType.InnerJoin)
.JoinAlias(x => x.Company, () => companyAlias, JoinType.InnerJoin);
var mapResult = MappingEngine.Map<IList<EmploymentDto>>(queryOver.List());
实体
public class Company
{
public virtual string Id { get; set; }
public virtual string A { get; set; }
public virtual bool B { get; set; }
public virtual bool C { get; set; }
}
public class Person
{
public virtual string Id { get; set; }
public virtual string D { get; set; }
public virtual string E { get; set; }
public virtual string F { get; set; }
}
public class Employment
{
public virtual Person Person { get; set; }
public virtual Company Company { get; set; }
public virtual string Description { get; set; }
public override bool Equals(object obj)
{
Employment toCompare = obj as Employment;
if (toCompare == null)
return false;
return (this.GetHashCode() != toCompare.GetHashCode());
}
public override int GetHashCode()
{
unchecked
{
int results = Person != null ? Person.GetHashCode() : 0;
results = (results * 397) ^ (Company != null ? Company.GetHashCode() : 0);
results = (results * 397) ^ (Description != null ? Description.GetHashCode() : 0);
return results;
}
}
}
映射
public class CompanyMap : SyncableClassMap<Company>
{
public CompanyMap()
{
Table("Company");
Id(x => x.Id).Column("Id").GeneratedBy.Assigned();
Map(x => x.A).Column("A");
Map(x => x.B).Column("B").CustomType<YesNoType>();
Map(x => x.C).Column("C").CustomType<YesNoType>();
}
}
public class PersonMap : SyncableClassMap<Person>
{
public PersonMap()
{
Table("Person");
Id(x => x.Id).Column("Id").GeneratedBy.Assigned();
Map(x => x.D).Column("D");
Map(x => x.E).Column("E");
Map(x => x.F).Column("F");
}
}
public class EmploymentMap : ClassMap<Employment>
{
public EmploymentMap()
{
Table("Employment");
CompositeId()
.KeyReference(x => x.Person, "Person_Id")
.KeyReference(x => x.Company, "Company_Id");
Map(x => x.Description, "Description");
}
}
公共类公司映射:SyncableClassMap
{
上市公司地图()
{
表(“公司”);
Id(x=>x.Id).Column(“Id”).GeneratedBy.Assigned();
映射(x=>x.A)。列(“A”);
Map(x=>x.B).Column(“B”).CustomType();
Map(x=>x.C).Column(“C”).CustomType();
}
}
公共类PersonMap:SyncableClassMap
{
公众人物地图()
{
表(“人”);
Id(x=>x.Id).Column(“Id”).GeneratedBy.Assigned();
映射(x=>x.D)。列(“D”);
映射(x=>x.E)。列(“E”);
映射(x=>x.F)。列(“F”);
}
}
公共类EmploymentMap:ClassMap
{
公共就业地图()
{
表(“就业”);
复合ID()
.KeyReference(x=>x.Person,“Person\u Id”)
.KeyReference(x=>x.Company,“Company_Id”);
地图(x=>x.描述,“描述”);
}
}
我遇到了与您在这里描述的相同的问题。我将以您的最后一个代码段为例,因为这是我使其工作的方式:
//This works, but the objects are still retrieved as PersonProxy and CompanyProxy,
var queryOver =
session.QueryOver<Employment>()
.JoinAlias(x => x.Person, () => personAlias, JoinType.InnerJoin)
.JoinAlias(x => x.Company, () => companyAlias, JoinType.InnerJoin);
var mapResult = MappingEngine.Map<IList<EmploymentDto>>(queryOver.List());
我无法向你解释为什么会这样,我只是根据自己的经验发现了这一点。如果执行左外部联接有问题,可以在执行映射之前(或同时)尝试在代码中进行相应的筛选。编辑后,我看到您有一个键引用,而不是正常的多对一 不幸的是,这似乎是QueryOver/Criteria的一个限制,即使指定了Fetchmode,QueryOver/Criteria也不会急于加载键引用。但是,Linq至NH没有此限制。将查询更改为
using NHibernate.Linq;
var results = session.Query<Employment>()
.Fetch(x => x.Person)
.Fetch(x => x.Company)
.ToList();
使用NHibernate.Linq;
var results=session.Query()
.Fetch(x=>x.Person)
.Fetch(x=>x.Company)
.ToList();
session.QueryOver().Fetch(x=>x.Person)。Eager.Fetch(x=>x.Company)。Eager
应该在不生成代理的情况下进行Eager Fetch。你确定你不过滤个人和公司吗?是的,我确定。然而,我和我们的系统架构师聊过,我们很可能会禁用懒散加载,所以在我们做出决定之前,我没有做过更多的研究。你能发布映射吗?我无法在示例应用程序中复制。我将尝试升级到最新版本的nHibernate,如果我仍然存在此问题,可以使用映射发回注释。升级不起作用。还是一样的问题。添加了映射到OPS,谢谢,但我仍然有同样的问题。越来越确信某个地方有bug。我和你做的完全一样,个人和公司的推荐信仍然是懒洋洋的。请注意,从NH生成的SQL如何缺少JOIN语句:NHibernate:选择this.Person\u Id作为Person1\u 72\u 0,this.Company\u Id作为Companyt2\u 72\u 0,this.Description作为Description作为Description 72\u 0这是刚升级的,仍然是相同的问题。我测试了你的答案,不幸的是它对我不起作用。