1

当谈到 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)); 

成一种方法。

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

4

3 回答 3

1

这是我通常使用的模式:

假设我有一个添加特定Restrictions条件的过滤器。(您甚至可以将其设为扩展类)

public class DeletedFlagFilter{

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

然后,上述类 say( 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);

使用上面的模式,您将在类中封装Deleted功能。DeletedFlagFilter将来,如果Deleted的定义发生更改,则唯一的更改将发生在DeletedFlagFilter类上

编辑:有很好的教程,你可以在这里阅读

于 2012-06-22T21:14:44.740 回答
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);
于 2012-06-22T21:14:53.863 回答
1

就个人而言,我更喜欢使用 Linq to 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")));

我还没有完全测试所有这些,但我希望你明白我的意思。我认为它非常易读,并且避免使用魔术字符串,因此它对重构很友好。

于 2012-06-22T21:29:22.297 回答