如何使用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
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();
没有一种简单的方法来打开或关闭该功能。总的来说,我认为有三种方法。
首先是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。
希望这篇评论能有所帮助…因为没有简单的方法来说:打开