所以我有一个使用SQLite数据库的应用程序。我有一些方法可以从我的数据库中获取模型。我有一个与我的数据库通信的存储库。它看起来像这样:
public class PhotoRepository
{
AppDatabase db = null;
public PhotoRepository ()
{
db = new AppDatabase (Constants.DatabaseFilePath);
}
public Photo GetPhoto(int id)
{
return db.GetItem<Photo>(id);
}
public IEnumerable<Photo> GetPhotos (int album_id)
{
return db.GetItems<Photo>().Where( x => x.Album_Id == album_id );
}
public int SavePhoto (Photo item)
{
return db.SaveItem<Photo>(item);
}
public int DeletePhoto(int id)
{
return db.DeleteItem<Photo>(id);
}
}
我关注GetPhotos(int album_id)
方法,因为它在我的数据库类中接近的方法如下所示:
public IEnumerable<T> GetItems<T> () where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return (from i in Table<T> () select i).ToList ();
}
}
正如您所看到的,它从我的数据库中检索所有照片模型,之后我将过滤那些与右album_id
对应的照片模型。
我的问题不是:
如何重写我的方法,以便它只取出与album_id
对应的模型。或者甚至更好,我如何重写此方法来过滤任何属性上的任何关系?
答案 0 :(得分:0)
所以我设法解决了自己的答案。也许人们对结果很感兴趣,所以来吧。
我读了一篇关于动态LINQ查询的帖子。我正在谈论的帖子可以找到here。所以我做的第一件事是创建一个Filter
类看起来像这样:
public class Filter
{
public enum Op
{
Equals,
GreaterThan,
LessThan,
GreaterThanOrEqual,
LessThanOrEqual,
Contains,
StartsWith,
EndsWith
}
public string PropertyName { get ; set ; }
public Op Operation { get ; set ; }
public object Value { get ; set ; }
}
然后我创建了ExpressionBuilder
类,如下所示:
public static class ExpressionBuilder
{
private static MethodInfo containsMethod = typeof(string).GetMethod("Contains" );
private static MethodInfo startsWithMethod =
typeof(string).GetMethod("StartsWith", new Type [] {typeof(string)});
private static MethodInfo endsWithMethod =
typeof(string).GetMethod("EndsWith", new Type [] { typeof(string)});
public static Expression<Func<T,
bool >> GetExpression<T>(IList<Filter> filters)
{
if (filters.Count == 0)
return null ;
ParameterExpression param = Expression.Parameter(typeof (T), "t" );
Expression exp = null ;
if (filters.Count == 1)
exp = GetExpression<T>(param, filters[0]);
else if (filters.Count == 2)
exp = GetExpression<T>(param, filters[0], filters[1]);
else
{
while (filters.Count > 0)
{
var f1 = filters[0];
var f2 = filters[1];
if (exp == null )
exp = GetExpression<T>(param, filters[0], filters[1]);
else
exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0], filters[1]));
filters.Remove(f1);
filters.Remove(f2);
if (filters.Count == 1)
{
exp = Expression .AndAlso(exp, GetExpression<T>(param, filters[0]));
filters.RemoveAt(0);
}
}
}
return Expression.Lambda<Func<T, bool>>(exp, param);
}
private static Expression GetExpression<T>(ParameterExpression param, Filter filter)
{
MemberExpression member = Expression.Property(param, filter.PropertyName);
ConstantExpression constant = Expression.Constant(filter.Value);
switch (filter.Operation)
{
case PhotoWapp.DL.Filter.Op.Equals:
return Expression.Equal(member, constant);
case PhotoWapp.DL.Filter.Op.GreaterThan:
return Expression.GreaterThan(member, constant);
case PhotoWapp.DL.Filter.Op.GreaterThanOrEqual:
return Expression.GreaterThanOrEqual(member, constant);
case PhotoWapp.DL.Filter.Op.LessThan:
return Expression.LessThan(member, constant);
case PhotoWapp.DL.Filter.Op.LessThanOrEqual:
return Expression.LessThanOrEqual(member, constant);
case PhotoWapp.DL.Filter.Op.Contains:
return Expression.Call(member, containsMethod, constant);
case PhotoWapp.DL.Filter.Op.StartsWith:
return Expression.Call(member, startsWithMethod, constant);
case PhotoWapp.DL.Filter.Op.EndsWith:
return Expression.Call(member, endsWithMethod, constant);
}
return null ;
}
private static BinaryExpression GetExpression<T>
(ParameterExpression param, Filter filter1, Filter filter2)
{
Expression bin1 = GetExpression<T>(param, filter1);
Expression bin2 = GetExpression<T>(param, filter2);
return Expression.AndAlso(bin1, bin2);
}
}
然后我添加了如下所示的方法GetItems<T>(List<Filter> filters)
:
public IEnumerable<T> GetItems<T> (List<Filter> filters) where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
var deleg = ExpressionBuilder.GetExpression<T> (filters).Compile ();
return (from i in Table<T>().Where(deleg) select i).ToList();
}
}
为了检索我需要的记录,我使用了以下代码。
public IEnumerable<Photo> GetPhotos (int album_id)
{
List<Filter> filters = new List<Filter> () {
new Filter{
PropertyName = "Album_Id",
Operation = Filter.Op.Equals,
Value = album_id
}
};
return db.GetItems<Photo>(filters);
}
现在我可以很好地过滤我需要的所有属性!关于这个解决方案的好处是我可以使用任何类和属性来过滤。
我希望这对某人有用!