假设我们有一个Category表和Product表。每个产品都引用了Category。所以每个类别都有很多产品。 我想加载许多没有产品的类别(减少数据库访问时间),然后检查我们实际需要的类别,并定义更少的类别子集。 在此之后,我需要加载所选类别的所有产品,并使用单个数据库查询将它们附加到类别。 我可以单独加载产品,但在这种情况下,它们不会附加到类别。
答案 0 :(得分:1)
这种解决方案本身就是在NHiberante中构建的。它被称为:
NHibernate可以有效地使用批量提取,也就是说,如果访问一个代理(或集合),NHibernate可以加载几个未初始化的代理。批量提取是懒惰选择提取策略的优化。有两种方法可以调整批处理获取:在类和集合级别上。
更容易理解批量提取类/实体。想象一下,您在运行时遇到以下情况:您在一个ISession中加载了25个Cat实例,每个Cat都有一个对其所有者的引用,一个Person。 Person类使用代理映射,lazy =“true”。如果您现在遍历所有猫并在每个猫上调用cat.Owner,NHibernate将默认执行25个SELECT语句,以检索代理所有者。您可以通过在Person:
的映射中指定批量大小来调整此行为
<class name="Person" batch-size="10">...</class>
NHibernate现在只执行三个查询,模式为10,10,5。
您还可以启用批量提取集合。例如,如果每个Person都有一个懒惰的Cats集合,并且当前在ISesssion中加载了10个人,则遍历所有人将生成10个SELECT,每个人调用一个SELECT.Cats。如果在Person的映射中为Cats集合启用批量获取,NHibernate可以预取集合:
<class name="Person">
<set name="Cats" batch-size="3">
...
</set>
</class>
摘要:有一个优化映射设置: batch-size="25"
。
我们可以在课堂级(稍后用于many-to-one
关系)或集合(直接在one-to-many
实现中)
这将导致很少的SELECT语句加载复杂的对象图。最重要的好处是,当我们查询根实体(没有多行)时,我们可以使用分页(Take()
,Skip()
检查also this,甚至更多链接......
答案 1 :(得分:1)
这可以通过HQL和期货来实现
给出实体和地图如下,
public class Category
{
private IList<Product> _products;
public Category()
{
_products = new List<Product>();
}
public virtual int Id { get; set; }
public virtual string CategoryName { get; set; }
public virtual IList<Product> Products
{
get { return _products; }
set { _products = value; }
}
}
public class CategoriesClassMap : ClassMap<Category>
{
public CategoriesClassMap()
{
Table("Categories");
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.CategoryName);
HasMany<Product>(c => c.Products).LazyLoad();
}
}
public class Product
{
public virtual int Id { get; set; }
public virtual string ProductName { get; set; }
public virtual Category Category { get; set; }
}
public class ProductSClassMap : ClassMap<Product>
{
public ProductSClassMap()
{
Table("Products");
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.ProductName);
References<Category>(x => x.Category).Not.Nullable();
}
}
使用以下HQL,它将在一个查询中加载所有类别和产品,
var categories = session.CreateQuery("from Category c join fetch c.Products where c.Id in (1,2)")
.Future<Category>().Distinct().ToList();
它只获取与类别id 1和2相关的数据。生成的SQL看起来像
select category0_.Id as Id1_0_, products1_.Id as Id3_1_, category0_.CategoryName as Category2_1_0_, products1_.ProductName as ProductN2_3_1_, products1_.Category_id as Category3_3_1_, products1_.Category_id as Category3_0__, products1_.Id as Id0__ from Categories category0_ inner join Products products1_ on category0_.Id=products1_.Category_id where category0_.Id in (1 , 2);
同样(使用未来)适用于queryover
或criteria