перевод запроса по коллекциям из SQL в nhibernate - PullRequest
1 голос
/ 10 июня 2011

У меня есть схема базы данных, где у меня есть Product, Category, CategoryFeature и ProductCategoryFeatureValue.

Модель сопоставлена ​​с использованием Fluent NHibernate, но в основном выглядит следующим образом.

Product
-------
ID
Title

Category
--------
ID
Title

CategoryFeature
---------------
ID
CategoryID
Title

ProductCategoryFeatureValue
---------------
ID
ProductID
CategoryFeatureID
_______________________

Category [one] <-> [many] CategoryFeature
Product [many] <-> [many] ProductCategoryFeatureValue

Основные функции, доступные для продукта, перечислены в таблице ProductCategoryFeatureValue, которая является «средней связью» для коллекции «многие ко многим».

Мне нужно создать запрос, где я могу найти все продукты, которые имеют ВСЕ функции, выбранные пользователем.

Например, выполняя поиск двух функций с идентификаторами 643229 и 667811 в терминах SQL, я бы сделал что-то вроде этого:

SELECT * FROM Product 
JOIN ProductCategoryFeatureValue AS feature1 ON Product.id = feature1.ProductID AND     feature1.categoryfeatureid = 643229
JOIN productcategoryfeaturevalue AS feature2 ON Product.id = feature2.ProductID AND feature2.categoryfeatureid = 667811

Другой запрос, который я мог бы сделать, это:

SELECT * FROM product WHERE 
((SELECT id FROM productcategoryfeaturevalue AS feature1 WHERE feature1.ItemGroupID = product.id AND feature1.categoryFeatureID = 643229 LIMIT 1) IS     NOT NULL)
AND 
((SELECT id FROM productcategoryfeaturevalue AS feature2 WHERE feature2.ItemGroupID = product.id AND feature2.categoryFeatureID = 667811 LIMIT 1) IS NOT NULL)

Оба были проверены и работают хорошо.Тем не менее, я не могу воспроизвести их с помощью NHibernate.Есть идеи?

Спасибо!

Ответы [ 3 ]

1 голос
/ 17 июня 2011

Я полагаю, что вы хотите что-то подобное в SQL

Select *
from Products p
where p.id in (
   select fv.ProductId
   from ProductCategoryFeatureValue fv
   where fv.CategoryFeatureID in (643229,643230)
   group by fv.ProductId
   having count(*)=@NumberOfDistinctFeaturesSelected 
)

Это избавит вас от необходимости присоединяться к таблице ProductCategoryFeatureValue несколько раз для каждой функции, выбранной пользователем.По крайней мере, вы собираетесь получить более хороший план запроса.Если вам не нравится предложение IN, вы также можете использовать временную таблицу.

С точки зрения перевода этого в NHibernate он не поддерживает какую-либо логику предложения HAVING в Criteria API, но поддерживается с использованием HQL.

Примеры HQL

var results = session.CreateQuery("from Product p where p.Id in (
    select fv.Product.Id
    from ProductCategoryFeatureValue fv
    where fv.CategoryFeature.Id in :featureids
    group by fv.Product.Id
    having count(fv)=:features
)")
.SetParameter("featureids", arrayOfFeatureIds)
.SetParameter("features", arrayOfFeatureIds.Count)
.List<Product>();
0 голосов
/ 21 июня 2011

Я думаю, что вашей самой большой проблемой является добавление условия для объединения. Я еще не пробовал, но с нетерпением жду возможности NH 3. +, которая позволит вам добавить критерий соединения.

CreateAlias ​​(ассоциация строкиPath, псевдоним строки, JoinType joinType, ICriterion withClause) CreateCriteria (ассоциация строкиPath, строковый псевдоним, JoinType joinType, ICriterion withClause)

0 голосов
/ 16 июня 2011

Не на 100% уверен в вопросе, каковы именно ваши сопоставления, но это может быть близко к тому, что вам нужно

object[] featureIds = new object[2];

featureIds[0] = 643229;
featureIds[1] = 667811;

ICriteria criteria = base.CreateCriteria(typeof(Product));
criteria.CreateAlias("ProductCategoryFeatureValueList", 
"ProductCategoryFeatureValue", JoinType.InnerJoin);
criteria.CreateAlias("ProductCategoryFeatureValue.CategoryFeatureID", 
"CategoryFeature", JoinType.InnerJoin);

criteria.Add(Expression.In("CategoryFeature.ID", featureIds));

Если «Expression.In» не вполне делает то, что вы после васмог бы просто сделать быстрый цикл добавления

criteria.Add(Expression.Eq("CategoryFeature.ID", featureIds[i]));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...