看一下下面的课程:
public class Produt
{
public virtual int id { get; set; }
public virtual string name { get; set; }
[ScriptIgnore]
public virtual Unit unit { get; set; }
}
public class Unit
{
public virtual int id { get; set; }
public virtual string name { get; set; }
public virtual IList<Produt> produts { get; set; }
}
在此之后,映射:
public partial class ProdutMap : ClassMap<Produt>
{
public ProdutMap()
{
Id(x => x.id).GeneratedBy.Identity();
Map(x => x.name).Length(100).Not.Nullable();
References(x => x.unit, "idUnit").Cascade.All().LazyLoad();
}
}
public partial class UnitMap : ClassMap<Unit>
{
public UnitMap()
{
Id(x => x.id).GeneratedBy.Identity();
Map(x => x.name).Length(100).Not.Nullable();
HasMany(x => x.produts).Cascade.All().KeyColumns.Add("idUnit").LazyLoad();
}
}
现在,想象一下我想执行这个查询:
SELECT produt.id, produt.name, unit.name FROM Produt, Unit WHERE produt.idUnit = unit.id
用nhibernate?怎么做?有什么帮助?
P.S。 [ScriptIgnore]是因为我遇到循环引用问题。我的课不仅仅是这些。这只是一个例子。
答案 0 :(得分:0)
最简单的方法是获取产品列表。产品已包含您需要的所有信息,因为它引用了Unit。
// NOTE: This fetches ALL products. You really should limit this.
var products = session.Query<Product>();
foreach (var product in products)
Console.WriteLine("Product: {0}, Unit: {1}", product.Name, product.Unit.Name);
在这个循环的每次迭代中,如果product.Unit
指向NHibernate尚未提取的单元,NHibernate将懒惰地执行另一个查询以获取该单元。
有时你无法使用延迟加载 - 也许你需要在迭代结果之前关闭NHibernate会话。此外,为了提高性能,最好减少到数据库的往返次数。我们可以通过改变我们的查询来解决这些问题:
var products = session.Query<Product>().Fetch(x => x.Unit);
如果由于某种原因,您需要扁平的结果对象,而不必通过嵌套对象来获取所需的数据,则可以使用“投影”来执行此操作。使用LINQ,这看起来像:
var productInfos = session.Query<Product>().Select(x => new
{
ProductId = x.Id,
ProductName = x.Name,
UnitName = x.Unit.Name
});
如果您需要限制NHibernate返回的列,这也很有用 - 例如,如果其中一列包含您想要避免获取的巨大BLOB。
除了LINQ之外,NHibernate还有几种不同的执行查询的方式:本机SQL,HQL,Criteria和QueryOver。对于Criteria或QueryOver,AliasToBean result transformer将在执行这些类型的查询时为您提供帮助。有关在条件查询中使用AliasToBean的示例,请参阅此相关问题:NHibernate - Only retrieve specific columns when using Critera queries?