在NHibernate中创建自定义标准?

时间:2012-06-22 20:50:57

标签: .net nhibernate nhibernate-criteria

对于NHibernate,我仍然是一个n00b。假设我有以下内容:

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)); 

进入方法。

这可能吗?这是如何工作的?

3 个答案:

答案 0 :(得分:1)

这是我经常使用的模式:

假设我有一个过滤器,可以在条件上添加特定的Restrictions。 (你甚至可以把它变成一个扩展类)

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会话的分离服务层然后可以将DetachedCriteria转换为连接到会话的条件并执行相同的操作。

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

  var sessionCriteria = myDetachedCriteria.GetExecutableCriteria(Session);

使用上面的模式,您可以在DeletedFlagFilter类中封装已删除的功能。将来,如果已删除的定义发生更改,则DeletedFlagFilter

会产生唯一的更改

修改:有一个很好的教程,你可以阅读here

答案 1 :(得分: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);

答案 2 :(得分: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")));

我还没有完全测试过所有这些,但我希望你能得到我的漂移。我认为它非常易读并且避免使用魔术字符串,所以它对重构很友好。