Производительность базы данных с Nhibernate и Activerecord - PullRequest
0 голосов
/ 18 ноября 2009

Вдохновленный рекламой DDD, я разработал свои классы, притворяясь, что базы данных вообще не было. А затем использовал NHibernate для сопоставления классов с таблицами базы данных. Часть моего графа классов выглядит следующим образом: Order (hasmany) -> Product (ownsto) -> Продавец. Чтобы получить все заказы, размещенные для определенного продавца. У меня есть код:

public class Order:ActiveRecordBase<Order>
{
    [HasMany]
    public ICollection<Product> Items{get;set;}
    ...
}

public class Product: Order:ActiveRecordBase<Product>
{
    [BelongsTo]
    public Seller Seller{get; set;} 
    ...
}

public class OrderRepository:IOrderRepository
{
    public IQuerable<Order> GetOrdersBySellerId(int sellerId)
    {
        return Order.FindAll().AsQuerable.Where(x=>x.Items.Count > 0 &&
                                                   x.Items.First().Seller.SellerID == sellerId).AsQuerable();

    }
}

Не очень, но это сработало с моими юнит-тестами. Я был счастлив, пока мы не начали вводить реальные данные в базу данных. Производительность настолько плохая, что хочется рвать. Итак, я провел небольшое исследование для своего кода репозитория. Неудивительно, что для того, чтобы найти нужные мне заказы, мне пришлось получить все данные из таблицы заказов, а также все данные из таблицы продуктов и некоторые данные из таблицы продавцов.

Итак, вот моя проблема. Как абсолютный дурак в области базы данных, я не знаю, как улучшить свой код репозитория, хотя знаю, что он плохо воняет. Поэтому у меня возникает соблазн изменить свой класс Order, чтобы иметь ссылку на класс Seller, чтобы я мог использовать hql для добавления предложения Where для повышения производительности. Но изменение структуры классов из-за проблем с базой данных, похоже, нарушает принципы DDD.

Что вы предлагаете, особенно в улучшении моего кода репозитория? Я пробовал Linq для ActiveRecord и hql. Но не мог заставить их работать.

Ответы [ 2 ]

0 голосов
/ 18 ноября 2009

После долгих исследований я получил это заявление hql

public IQuerable<Order> GetOrdersBySellerId(int sellerId)
{
     string hql = @"select  o 
                    from     Order o, Product p
                    where    p.Seller.SellerID=:sellerID
                    and      p in elements(o.Items )";

     SimpleQuery<Order> q = new SimpleQuery<Order>(hql);
     q.SetParameter("sellerID", sellerID);
            return q.Execute().AsQueryable();
}

Спасибо за этот пост. Я понял идею из ответа Айенде. Пожалуйста, дайте мне знать, если это загрузит производительность.

0 голосов
/ 18 ноября 2009

Хотя AFAIK ActiveRecord не имеет прямой поддержки LINQ, вы можете использовать LINQ для провайдера NHibernate. Здесь - образец. В конце приведен пример использования более традиционных и зрелых критериев API.

ОБНОВЛЕНИЕ: Извините, я был не прав. Похоже, вам нужно наследовать ваши сущности от ActiveRecordLinqBase<T> и создавать запросы, используя его свойство Queryable.

Это должно выглядеть как

public IQuerable<Order> GetOrdersBySellerId(int sellerId)
{
    return Order.Queryable
               .Where(x=>x.Items.Count > 0 && x.Items.First().Seller.SellerID == sellerId)();
}

Если вы хотите придерживаться простого ActiveRecordBase<T>, вы можете использовать статический метод ActiveRecordLinq.AsQueryable<T>().

public IQuerable<Order> GetOrdersBySellerId(int sellerId)
{
    return ActiveRecordLinq.AsQueryable<Order>()
               .Where(x=>x.Items.Count > 0 && x.Items.First().Seller.SellerID == sellerId)();
}

Вы пробовали это с вашими критериями поиска? (Я спрашиваю это, потому что AFAIK, вы не все конструкции LINQ работают на NHibernate)

...