我写了一个多层应用程序(数据访问层,业务层,UILayer) 在DAL中我使用NHibernate来访问DB
然后在BusinessLayer中我访问DAL以使用存储库接口获取一些数据。
有时我需要通过困难的查询来获取数据。现在我使用Linq
来提取数据。
我尝试在实现Criterion
逻辑的存储库中编写metods,但是我认为,增长被覆盖方法的数量是错误的。
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();
那么如何在没有参考的情况下在BL中使用NHibernate.Criterion逻辑?
---- ---解
我创建了课程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();
答案 0 :(得分:1)
如何打开或关闭该功能并不容易。总的来说,有三种方法,我要说。
第一个是MS及其LINQ。要做到这一点,只需使用
var query = session.Query<TEntity>()
我们(上层)现在可以根据需要查询该实体...只需使用LINQ API。缺点是NHibernate提供程序中没有完全覆盖LINQ - 但最终并没有那么糟糕。我不喜欢的是你发布了很多你的域名...没有一些属性或其他AOP ......只要有一个IQueryable就可以获得整个系统。
第二种是Ayendes方法:The DAL should go all the way to UI。小引用:
......我目前的方法完全不同。我定义了查询,其中包含查询的实际业务逻辑,但我将该查询向前传递到我的应用程序的更高级别。可以对查询(投影,分页,排序等)进行任何其他处理。这样,我的查询将被关闭以进行修改并打开扩展,因为它们可以被更高级别的代码进一步操纵...
在此处详细了解它:How to organize database layer using NHibernate
第三种选择是使用一些自定义解决方案。例如。我首选的是引入一些名为IFilter
的抽象,它通过层传递。填写UI (可能是基于API的客户端),在BL上检查所有规则(包括一些安全的AOP)并在DAL中使用..并转换为NHibernate Criteria API。
希望这篇评论有所帮助...因为没有简单的方法可以说:在上转过来。