我有两个由以下实体建模的表:
public class Product : ModifiableEntity
{
public virtual int ProductId { get; set; }
public virtual string Description { get; set; }
public virtual ProductStats Stats { get; set; }
}
public class ProductStats : ModifiableEntity
{
public virtual int ProductStatId { get; set; }
public virtual int? QtyAvail { get; set; }7
public virtual Product Product { get; set; }
}
使用以下流畅的映射:
public class ProductMap : ModifiableEntityClassMap<Product>
{
public ProductMap()
{
Table("Product");
Id(x => x.ProductId).Column("ProductId").GeneratedBy.Identity();
Map(x => x.Description).Column("Description").Nullable().Length(Int32.MaxValue);
HasOne(x => x.Stats)
.PropertyRef(x => x.Product)
.Cascade.All();
}
}
public class ProductStatsMap : ModifiableEntityClassMap<ProductStats>
{
public ProductStatsMap()
{
Table("ProductStats");
Id(x => x.ProductStatId).Column("ProductStatId").GeneratedBy.Identity();
Map(x => x.QtyAvail).Column("QtyAvail").Nullable();
References(x => x.Product).Column("ProductId")
.Unique()
.Cascade.All()
.Not.Nullable();
}
}
我的测试数据库中有7005个产品,产品和产品统计信息之间的内部联接是1比1并返回7005条记录,但是当我运行以下查询时,我在SQL事件探查器中看到了近30,0000个查询。
var products = from p in _productRepository.Linq()
select p;
我尝试过各种变体:
HasOne(x => x.Stats)
.Not.LazyLoad().Fetch.Join()
.PropertyRef(x => x.Product)
.Cascade.All();
除了在linq查询中指定fetch之外,无论我尝试什么,结果都是针对我的SQL服务器运行了数万个查询。
任何人都可以提供任何帮助,我们将不胜感激。
提前谢谢。
答案 0 :(得分:0)
我认为这里的问题是您需要急切加载 ProductStats 。您可以通过两种方式实现这一目标:
在映射Stats属性时添加 .Not.LazyLoad(),如下所示:
HasOne(x => x.Stats)
.PropertyRef(x => x.Product)
.Not.LazyLoad()
.Cascade.All();
或
使用命名空间 NHibernate.Linq ,如下所示:
session.Query<Product>().Fetch(p => p.Stats).ToFuture();
这将使NHibernate仅在一次数据库往返中执行两个查询。第一个查询将获取产品,第二个查询将获取在第一个产品中获取的每个productStats。
第一种方法的唯一问题是它会影响您执行的每个查询。另一方面,只有在真正需要时才能使用第二种方法。
尽管如此,仍有一些问题困扰着我:你真的需要&#34;产品&#34;属性中的属性?因为你可能在循环引用方面遇到一些问题。