无需加入即可运行NHibernate查询

时间:2010-09-23 08:10:50

标签: .net database nhibernate lazy-loading

我有Fluent映射,将虚构的类Customer映射到Orders列表。现在我想从数据库中获取所有客户而不加载订单。这可以在查询/标准/ etc中以某种方式指定,还是LazyLoading唯一的解决方案?

虚构课程:

public class Customer
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Order> Orders { get; set; }
}

public class Order
{
    public virtual int Id { get; set; }
    // ++ 
}

2 个答案:

答案 0 :(得分:2)

无论如何,延迟加载会自动执行此操作,您是否尝试避免延迟加载?为什么呢?

例如:

IList<Customer> customers = _session.CreateCriteria<Customer>().List<Customer>();

仅为您提供所有客户。只有在客户实体上调用Order集合时,才会从数据库中获取订单,例如:

foreach(Customer customer in customers)
{
    IList<Order> orders = customer.Orders; // Will hit the database
}

因此,如果您有10个客户,此代码将在数据库中点击11次(1个用于获取客户,10个用于检索每个客户的订单)。这会给你一个SELECT N + 1问题,但如果你对每个客户的订单不感兴趣,那么就不要调用Orders,它们也不会被提取。我不是故意粗鲁,但这似乎相当明显,我是否误解了你的问题?


更新:回应评论。如果通过Web服务发送POCO,您应该考虑使用报表查询,因为您的POCO将丢失其对NHibernate会话对象的附件,因此延迟加载将不起作用(Orders集合将只返回NULL)。换句话说,正确调用您的Web服务的“事物”不会对NHibernate或您的域模型有任何了解,所以:

public IList<CustomerView> GetAllCustomers()
{
    return (from c in _session.Query<Customer>()
            select new CustomerView()
            {
                Id = c.Id,
                Name = c.Name
            }).ToList();
}

public CustomerDetail GetCustomerFromId(int id)
{
    return (from c in _session.Query<Customer>()
            where c.Id == id
            select new CustomerDetail()
            {
                Id = c.Id,
                Name = c.Name
                FullAddress = c.FormatFullAddress(),
                Orders = c.Orders,
                // other properties (snip)
            }).SingleOrDefault();
}

这是使用NHibernate 3.0内置的LINQ提供程序,如果您不使用NHibernate 3.0,并且可以使用Projections进行报表查询。语法逃脱了我,请尝试http://nhibernate.info/doc/nh/en/index.html#querycriteria-projection

答案 1 :(得分:1)

您可以在条件中指定FetchMode:

var crit = session.CreateCriteria (typeof(SomeObject));
crit.SetFetchMode ("association", FetchMode.Eager);

您还可以在映射中指定不应延迟加载关联/集合。默认情况下,集合是延迟加载的。