I write a multi-tier app (Data Access Layer,Business Layer, UILayer) in DAL I use NHibernate to access to DB
then in BusinessLayer I access to DAL to get some data using interface for repository.
And sometimes I need to get data by difficult query. Now I use Linq
to extracted data.
I try to wrote metods in repository that implements Criterion
logic,but grows up number of overridden methods is wrong way, I think.
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>();
}
but more and more I need to create difficult criteria to query (I dont like idea of extract all data and filtering it by Linq
)
example for criteria that I want to use in BL:
repository.GetMany(x=>
x.Prop1.IsIn(Collection1)&&
x.Prop2.IsIn(Collection2)&&
x.Prop3.IsLike("SomeData")).ToList();
So how I can to use NHibernate.Criterion logic in BL without referensing?
----SOLUTION---
I created class 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;
}
}
And wrote Method in 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;
}
To Use filter I call
var docs = docRepo.GetByFilter(
new CustomFilter<Doc>()
.In(x => x.Archive, arcs)
.Top(200)
).ToList();