2012-06-22 3 views
1

Я все еще немного n00b, когда дело доходит до NHibernate. Скажем, у меня есть следующие:Создать пользовательский критерий в NHibernate?

var myCriteria = this.Session.CreateCriteria(typeof(SomeModel)) 
         .Add(Restrictions.Eq("SomeProperty", someValue); 

Тогда, скажем, я хочу, чтобы добавить критерии в способе, которым это многоразовые. Смысл, я хочу сделать собственный критерий. Я вижу очень, очень мало информации в Интернете по этому поводу. В частности, я хотел бы включить следующие:

var myCriteria = this.Session.CreateCriteria(typeof(SomeModel)) 
       .Add(Restrictions.Eq("SomeProperty", someValue) 
       .CreateAlias("SomeClass", "alias", JoinType.LeftOuterJoin) 
       .Add(Restrictions.Eq("alias.SomeOtherProperty", someOtherValue)); 

В следующее:

var myCriteria = this.Session.CreateCriteria(typeof(SomeModel)) 
          .Add(Restrictions.Eq("SomeProperty", someValue) 
          .Add(this.GetAliasCriterion()); 

Таким образом, извлекая

 .CreateAlias("SomeClass", "alias", JoinType.LeftOuterJoin) 
      .Add(Restrictions.Eq("alias.SomeOtherProperty", someOtherValue)); 

в метод.

Возможно ли это? Как это работает?

+1

Почему бы вам не попробовать DetachedCriteria – frictionlesspulley

ответ

1

Лично я предпочитаю использовать Linq для NHibernate вместо критериев. Он уже включен в последнюю версию NHibernate, просто добавьте «using NHibernate.Linq» в ваш файл cs, так как все методы L2H являются методами расширения.

Если я хочу сделать предикат/критерии для повторного использования с L2H, это будет выглядеть примерно так:

public partial class Person 
{ 
    //yes, this is kind of ugly, but if I have a complicated predicate that 
    //I want to reuse, I'll make a static method on the entity itself. 
    public static Expression<Func<Person, bool>> HasPrimaryRole(string roleCode) 
    { 
     return p => p.Roles.Any(r => r.RoleCode == roleCode && r.IsPrimary); 
    } 
} 

Использование выглядит следующим образом:

var session = GetSession(); 
var midwestSalesManagers = session.Query<Person>() 
    .Where(p => p.Region == "Midwest").Where(Person.HasPrimaryRole("RSM")); 

или в качестве альтернативы вы можете сделать это :

var midwestSalesManagers = session.Query<Person>() 
    .Where(Expression.And(p => p.Region == "Midwest", Person.HasPrimaryRole("RSM"))); 

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

+0

Gee, этот синтаксис намного лучше. Давайте посмотрим, смогу ли я получить всю команду из двадцати, чтобы отменить курс и переписать весь их уровень доступа к данным ... да, это, вероятно, не произойдет. Жаль, что это мой первый опыт использования NHibernate, и я получил этот проект через пару месяцев:/ Кто знает, может быть, они не возражают, если я напишу новый материал таким образом? – vbullinger

1

Это шаблон, который я обычно использую:

Говорит, что у меня есть фильтр, который добавляет определенную Restrictions на критерии. (Вы можете даже сделать это классом Extension)

public class DeletedFlagFilter{ 

    public DetachedCriteria AddFilter(DetachedCriteria criteria) 
    { 
     criteria.AddRestrictions("Deleted", true); 
     return criteria; 
    } 
} 

Вызывающими указанного класс говорят (FindDeletedUserClass) затем будет затем использовать вспомогательный класс выше, чтобы добавить все ограничения, необходимые для определения, какой удаленного пользователя следующим образом:

public class FindDeletedUserClass{ 

     public DetachedCriteria BuildCriteria(){ 

      var deletedUserCriteria = DetachedCriteria.For<User>();   

      var helper = new DeletedFlagFilter(); 

      helper.AddFilter(deletedUserCriteria); 

      return deletedUserCriteria; 

     } 
} 

Вашего отделенная служба слой, который фактически обращается к NHibernate сессии затем может CONVER в DetachedCriteria критерии, подсоединенных к сессии и выполнить то же самое, как.

var myDetachedCriteria = DetachedCriteria.For<SomeModel>(); 

    var sessionCriteria = myDetachedCriteria.GetExecutableCriteria(Session); 

Используя рисунок выше, вы бы инкапсулировать Deleted функциональность в DeletedFlagFilter классе. В будущем, если определение Удаляется изменяет только изменения будут понесены на DeletedFlagFilter класса

Edit: есть хороший учебник, который вы могли бы прочитать here

+0

Спасибо. Я проверю эту ссылку. Я получаю это от этого, и это похоже на возможность. Я поддержал вас и, если это именно то, что мне нужно, я приму этот ответ. В любом случае, все еще хорошее предложение. – vbullinger

1

Вы можете сделать это с помощью метода расширения , Я был бы осторожен, хотя обычно вам нужно увидеть все псевдонимы (объединения), которые выполняет запрос.

public static class CriteriaExtensions 
{ 
    public static ICriteria AddSomeClassAliasRestriction(this ICriteria c, object value) 
    { 
     return c.CreateAlias("SomeClass", "alias", JoinType.LeftOuterJoin) 
      .Add(Restrictions.Eq("alias.SomeOtherProperty", value)); 
    } 
} 

и использовать его как ...

var myCriteria = this.Session.CreateCriteria(typeof(SomeModel)) 
.Add(Restrictions.Eq("SomeProperty", someValue) 
.AddSomeClassAliasRestriction(someOtherValue); 
+0

Это отличное предложение для некоторых сценариев, но не мое. Поэтому я подниму это и буду держать в уме для будущего использования. Но это не то, что я хотел бы использовать для более чем одного класса DAO. – vbullinger

+0

привет, не могли бы вы уточнить свой вопрос? Пока неясно, о чем вы просите. – dotjoe

+0

Все, что я говорю, заключается в том, что создание метода расширения, когда это не будет использоваться за пределами одного класса, немного переборщит. Но это сработает, следовательно, вверх. – vbullinger

Смежные вопросы