Выполнение запросов NHibernate без присоединения - PullRequest
3 голосов
/ 23 сентября 2010

У меня есть Fluent mappings, который отображает вымышленный класс Customer в список заказов. Теперь я хочу получить всех клиентов из базы данных без загрузки заказов. Можно ли это как-то указать в запросе / критерии / и т.д., или 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 ]

2 голосов
/ 23 сентября 2010

Ленивая загрузка делает это автоматически в любом случае, вы пытаетесь избежать отложенной загрузки? Почему?

Например:

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

Даст вам всех клиентов только. Заказы будут извлечены из базы данных только при вызове коллекции заказов для объекта Customer, например:

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

Таким образом, если у вас есть 10 клиентов, этот код попадет в базу данных 11 раз (1 для получения клиента, 10 для получения заказов для каждого клиента). Это создает проблему SELECT N + 1, хотя, если вас не интересуют Заказы для каждого клиента, просто не вызывайте Заказы, и они не будут выбраны. Я не хочу быть грубым, но это кажется довольно очевидным, я неправильно понимаю ваш вопрос?


Обновление: В ответ на комментарии. Вам следует рассмотреть возможность использования запроса отчета при отправке ваших POCO через веб-сервис, поскольку ваши POCO потеряют свое вложение в объекте NHibernate Session, и, следовательно, отложенная загрузка не будет работать (коллекция Orders просто вернет NULL). Другими словами, «вещь», вызывающая ваш веб-сервис должным образом, ничего не будет знать о 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();
}

При этом используется поставщик LINQ, встроенный в NHibernate 3.0, если вы не используете NHibernate 3.0 и можете выполнять запросы отчетов с использованием проекций. Синтаксис ускользает от меня, поэтому попробуйте здесь http://nhibernate.info/doc/nh/en/index.html#querycriteria-projection

1 голос
/ 23 сентября 2010

Вы можете указать FetchMode в Критериях:

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

Вы также можете указать в отображении, что ассоциация / коллекция также не должна загружаться с отложенным доступом.По умолчанию коллекции загружаются лениво.

...