如何使用NHibernate.在不使用NHibernate引用的情况下,应用程序的上层标准

本文关键字:NHibernate 情况下 应用程序 标准 引用 何使用 | 更新日期: 2023-09-27 18:07:26

我写了一个多层应用程序(数据访问层,业务层,用户层)在DAL中,我使用NHibernate来访问数据库

然后在BusinessLayer I访问DAL以使用存储库接口获取一些数据。

有时我需要通过困难的查询来获取数据。现在我使用Linq来提取数据。

我尝试在实现Criterion逻辑的存储库中编写方法,但我认为增加覆盖方法的数量是错误的。

public T GetBy(System.Linq.Expressions.Expression<Func<T, bool>> func)
{
    return _session.QueryOver<T>().Where(func).List().FirstOrDefault();
}
public IEnumerable<T> GetAllWhere(System.Linq.Expressions.Expression<Func<T, bool>> func)
{
    return _session.QueryOver<T>().Where(func).List();
}
public IEnumerable<T> GetAllIn(ICollection collection)
{
    return _session.QueryOver<T>().Where(x => x.Id.IsIn(collection)).List<T>();
}

但越来越多的我需要创建困难的标准来查询(我不喜欢提取所有数据并通过Linq过滤它的想法)我想在BL中使用的标准示例:

repository.GetMany(x=>
                     x.Prop1.IsIn(Collection1)&&
                     x.Prop2.IsIn(Collection2)&&
                     x.Prop3.IsLike("SomeData")).ToList();

我该如何使用NHibernate。没有引用的BL中的标准逻辑?

——解决方案——

创建类Filter

public class CustomFilter<T>
        where T : Entity
    {
        public class FilterQuery
        {
            public enum QueryType
            {
                In, Where, Like, LikeIn,Top
            }
            public QueryType QType { get; set; }
            public Expression<Func<T,object>> Selector { get; set; }
            public object Data { get; set; }
            public FilterQuery(QueryType qType, Expression<Func<T,object>> selector, object data)
            {
                QType = qType;
                Selector = selector;
                Data = data;
            }
        }
        public  List<FilterQuery> Queries = new List<FilterQuery>();
        public  CustomFilter<T> In(Expression<Func<T, object>> selector, ICollection collection) 
        {
            var query = new FilterQuery(FilterQuery.QueryType.In, selector, collection);
            Queries.Add(query);
            return this;
        }
        public CustomFilter<T> Top(int i)
        {
            Queries.Add(new FilterQuery(FilterQuery.QueryType.Top, null,i));
            return this;
        }
    }

并在Repository

中编写Method
public IEnumerable<T> GetByFilter(CustomFilter<T> filter)
        {
            IQueryOver<T,T> query = _session.QueryOver<T>();
            foreach (var _filter in filter.Queries)
            {
                switch (_filter.QType)
                {
                   case CustomFilter<T>.FilterQuery.QueryType.In:
                        query = query.WhereRestrictionOn(_filter.Selector)
                                     .IsIn((ICollection)_filter.Data);
                        break;
                   case CustomFilter<T>.FilterQuery.QueryType.Top :
                        query = (IQueryOver<T, T>) query.Take((int)_filter.Data);
                        break;
                }
            }
            return query != null ? query.List<T>() : null;
        }

使用过滤器,我调用

 var docs = docRepo.GetByFilter(
                        new CustomFilter<Doc>()
                        .In(x => x.Archive, arcs)
                        .Top(200)
                        ).ToList();

如何使用NHibernate.在不使用NHibernate引用的情况下,应用程序的上层标准

没有一种简单的方法来打开或关闭该功能。总的来说,我认为有三种方法。

首先是MS和它的LINQ。为此,只需使用

var query = session.Query<TEntity>()

我们(上层)现在可以根据需要查询该实体…只是使用LINQ API。缺点是在NHibernate提供程序中没有完全覆盖LINQ,但最后它并没有那么糟糕。我不喜欢的是你发布了很多你的域名…没有一些属性或其他AOP…用一个IQueryable你可以得到整个系统。

第二个是Ayendes方法:DAL应该一直到UI。小引用:

…我目前的做法是完全不同的。我定义查询,其中包含查询的实际业务逻辑,但我将该查询传递给应用程序的更高级别。查询上的任何附加处理(投影、分页、排序等)都可以完成。这样,我的查询对修改是关闭的,对扩展是开放的,因为它们可以被更高级的代码进一步操纵…

在这里阅读更多信息:如何使用NHibernate组织数据库层

第三个选择是使用一些定制的解决方案。例如,我更喜欢引入一些抽象,称为IFilter,它是通过层传递的。在UI 上填充(可能是客户端通过API),在BL上检查所有规则(包括一些用于安全性的AOP),并在DAL中使用。并转换为NHibernate标准API。

希望这篇评论能有所帮助…因为没有简单的方法来说:打开