问题描述
我的 hbm 配置:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-cascade="save-update" default-lazy="false">
<class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.CompanyBanan,LittleNHibernateProject,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null" table="CompanyBanan">
<cache region="CompanyBanan" usage="read-write" />
<id name="Id" type="System.Int64,mscorlib,Version=4.0.0.0,PublicKeyToken=b77a5c561934e089">
<column name="Id" />
<generator class="increment" />
</id>
<version generated="always" name="VersionObject" type="System.Int64,PublicKeyToken=b77a5c561934e089" unsaved-value="0">
<column name="VersionObject" not-null="true" default="1" />
</version>
<many-to-one class="LittleNHibernateProject.Model.FatherBanan,PublicKeyToken=null" foreign-key="FK_CompanyBanan_FatherBanan" name="FatherBanan">
<column name="FatherBanan_id" />
</many-to-one>
<property name="Name" type="System.String,PublicKeyToken=b77a5c561934e089">
<column name="Name" />
</property>
</class>
<class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.JobBanan,PublicKeyToken=null" table="JobBanan">
<cache region="JobBanan" usage="read-write" />
<id name="Id" type="System.Int64,PublicKeyToken=b77a5c561934e089" unsaved-value="0">
<column name="VersionObject" not-null="true" default="1" />
</version>
<any id-type="System.Int64,PublicKeyToken=b77a5c561934e089" meta-type="System.String,PublicKeyToken=b77a5c561934e089" name="Banan">
<meta-value value="MotherBanan" class="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" />
<meta-value value="FatherBanan" class="LittleNHibernateProject.Model.FatherBanan,PublicKeyToken=null" />
<column name="Banan_Type" />
<column name="Banan_Id" />
</any>
<property name="JobName" type="System.String,PublicKeyToken=b77a5c561934e089">
<column name="JobName" />
</property>
</class>
<class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.FatherBanan,PublicKeyToken=null" table="FatherBanan">
<cache region="FatherBanan" usage="read-write" />
<id name="Id" type="System.Int64,PublicKeyToken=b77a5c561934e089" name="WifeBanan">
<meta-value value="MotherBanan" class="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" />
<column name="Banan_Type" />
<column name="Banan_Id" />
</any>
<property name="Name" type="System.String,PublicKeyToken=b77a5c561934e089">
<column name="Name" />
</property>
<property name="Variety" type="System.String,PublicKeyToken=b77a5c561934e089">
<column name="Variety" />
</property>
</class>
<class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true" dynamic-update="true" optimistic-lock="version" name="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" table="MotherBanan">
<cache region="MotherBanan" usage="read-write" />
<id name="Id" type="System.Int64,PublicKeyToken=b77a5c561934e089" name="HusbandBanan">
<meta-value value="MotherBanan" class="LittleNHibernateProject.Model.MotherBanan,PublicKeyToken=null" />
<column name="Banan_Type" />
<column name="Banan_Id" />
</any>
<property name="Variety" type="System.String,PublicKeyToken=b77a5c561934e089">
<column name="Variety" />
</property>
</class>
</hibernate-mapping>
我只需要选择加载了标识符的根实体和内部实体(我与 statlesssession 一起使用)。 如果我想选择FatherBanan,我使用扩展名:
public static List<FatherBanan> ToOnlyRefList(this IQueryable<FatherBanan> query)
{
var select = query.Select(sel => new {sel.Id,sel.Name,sel.Variety,WifeId = sel.WifeBanan.Id,sel.VersionObject}).ToList();
var result = new List<FatherBanan>();
foreach (var item in select)
{
result.Add(new FatherBanan
{
Id = item.Id,Name = item.Name,Variety = item.Variety,VersionObject = item.VersionObject,WifeBanan = new MotherBanan{Id = item.WifeId}
});
}
return result;
}
选择FatherBanan:
using (var sss = factorySession.OpenSession())
{
var list = sss.Query<FatherBanan>().ToOnlyRefList();
}
而且Nhibernate从FatherBanan表生成SQL,没问题。
但是如果我想选择 JobBanan:表达式选择新不起作用,生成异常不要将 JobBanan 转换为 Banan。好的,通过使用扩展解决了它的异常:
public static List<JobBanan> ToOnlyRefList(this IQueryOver<JobBanan,JobBanan> query)
{
var select = query
.Select(
Projections.Property("Id"),Projections.Property("JobName"),Projections.Property("VersionObject"),Projections.SqlProjection("banan_id as banan_id",new[] { "banan_id" },new IType[] { NHibernateUtil.Int64 }),Projections.SqlProjection("banan_type as banan_type",new[] { "banan_type" },new IType[] { NHibernateUtil.String })
).List<object[]>();
var result = new List<JobBanan>();
foreach (var item in select)
{
Banan banan = null;
if (item[4] as string == nameof(FatherBanan))
{
banan = new FatherBanan() { Id = (long)item[3] };
}
else
if (item[4] as string == nameof(MotherBanan))
{
banan = new MotherBanan { Id = (long)item[3] };
}
result.Add(new JobBanan
{
Id = (long)item[0],JobName = (string)item[1],VersionObject = (long)item[2],Banan = banan
});
}
return result;
}
我得到了所有的香蕉 sss.Query<Banan>.ToOnlyRefList()
?
解决方法
我找到了一种方法 - 将所有嵌套在循环中:
var types = new Type[]{/*all type in Any mapping Banan*/};
var result = new List<Banan>();
foreach(var type in types)
{
result.AddRange(sss.Query(type.FullName).ToOnlyRefList());
}
如果实体(和内部实体)不是抽象的,那么:
using (var session = factorySession.OpenSession())
{
var banan =
session
.Query<CompanyBanan>()
.Select( sel => new
{
sel.Id,BananId = sel.FatherBanan == null ? (long?)null : sel.FatherBanan.Id,sel.Name,sel.VersionObject
})
.ToList()
;
}
//and convert typle to entity extension
这将生成 SQL:
select
companyban0_.Id as col_0_0_,case when fatherbana1_.Id is null then TRUE else FALSE end as col_1_0_,companyban0_.FatherBanan_id as col_2_0_,companyban0_.Name as col_3_0_,companyban0_.VersionObject as col_4_0_
from CompanyBanan companyban0_
left outer join FatherBanan fatherbana1_ on companyban0_.FatherBanan_id=fatherbana1_.Id