Я пытаюсь оценить NHibernate.LINQ 1.0 без фактического написания кода. Айенде признался, что эта версия поддержки LINQ является подпарами по сравнению с EF, но для жизни меня я не могу найти страницу, которая объясняет, что поддерживается и не поддерживается в этой реализации. Например, можно ли использовать Skip
и Take
? Что я не могу использовать?
Поддерживаемые операторы NHibernate.LINQ
Ответ 1
Вы можете проверить LINQ для NHibernate примеры, чтобы увидеть тесты, выполненные самим Айенде, о том, что реализовано, а что нет этого провайдера.
Некоторые из них обычно поддерживаются:
- Создание анонимного типа.
new { Person = x.Name }
- Первый().
query.First()
- FirstOrDefault().
query.FirstOrDefault()
- Один().
query.Single()
- SingleOrDefault().
query.SingleOrDefault()
- Совокупный().
query.Aggregate((x1,x2) => x1)
- Contains().
query.Where(x => x.Name.Contains("Foo"))
- StartsWith().
- EndsWith().
- подстрока().
where db.Methods.Substring(e.FirstName, 1, 2) == "An"
- Sub-запросы.
query.Where(x => x.Company.Id == 4)
- Count().
query.Where(x => x.Relatives.Count > 0)
- Любой().
query.Any()
- Возьмите().
query.Take(10)
- Пропустить().
query.Take(10).Skip(4)
- OrderBy().
orderby x.Name descending
- Заменить().
AfterMethod = e.FirstName.Replace("An", "Zan"),
- CHARINDEX().
where db.Methods.CharIndex(e.FirstName, 'A') == 1
- IndexOf().
where e.FirstName.IndexOf("An") == 1
Проблемные:
- Группа
- Соединения
Один из моих собственных примеров:
query = NSession.Session.Linq<Catalog>() .Where(acc => acc.Company.Status == "A") .Where(acc => acc.Id.StartsWith("12-536")) .Where(acc => acc.Id.EndsWith("92") || acc.Id.EndsWith("67")) .Take(10).OrderBy(acc => acc.Title);
Если вы производственное приложение использует самую последнюю стабильную версию 2.1.2.4, как я, вы застряли в том, что дает нам поставщик NHibernate.Linq, пока NHibernate 3.0 (trunk) не получит стабильную версию, и мы чувствуем себя в безопасности использовать его в основных приложениях. До тех пор я более чем доволен смесью NHibernate.Linq и HQL.
Ответ 2
Основная проверка того, может ли NHibernate работать с оператором Linq, состоит в том, можно ли сериализовать это дерево выражений оператора, затем десериализовать его в другом процессе и получить правильный ответ. Это означает отсутствие внешних замыканий; лямбда должна работать только с тем, что она создает или задается в качестве параметра.
Linq2NH 1.0, IIRC, также дросселируется при использовании членов класса, которые не отображаются, поэтому, если, например, у вас есть рассчитанное на чтение свойство, такое как специальный взвешенный или скользящий средний, вы должны сопоставить его с БД чтобы ссылаться на нее в лямбда (или воссоздать логику в лямбда). Это связано с тем, что дерево выражений в конечном итоге сводится к SQL (через один из NH-промежуточных элементов, в 2.x это ICriteria, в 3.x это HQL), и если NH не может принять выражение и преобразовать его 1:1 в SQL выражение, которое будет успешно оцениваться, оно просто не будет работать.
Существует один специальный случай: Linq2NH, IIRC, достаточно умен, чтобы превратить выражение IList.Contains() в предложение IN. Список должен быть определен в лямбда (например, new[]{"1","2"}.Contains(m.ID)
).
Ответ 3
Сообщение в блоге от Айенде с мая этого года. Многое изменилось. NHiberante. Linq 1.0 linq-провайдер устарел с года примерно из-за нового провайдера linq в NHibernate Trunk. Новый провайдер linq еще не полностью завершен, но уже очень полный и пригодный для использования гораздо больше, чем старый поставщик linq. Вещи, которые не работают с новым провайдером linq, считаются ошибками и будут решены когда-нибудь, когда будут сообщены.
Вы можете использовать пропустить и взять со старым и новым провайдером linq. Текущий список известных проблем можно найти на NHibernate Jira. Другие проблемы неизвестны, и все остальные функции уже поддерживаются.