rei*_*ard 9 c# linq extension-methods
我经常有这样的代码:
var stRecs = db.<someTable>
.Where(a => a.DepID == depID)
Run Code Online (Sandbox Code Playgroud)
选择单个记录,但是如果depID == 0
我想取回所有记录.
我正在考虑创建一个扩展方法"WhereDepID_OrAll",就像
public static IQueryable<T> WhereDepID_OrAll<T>(this IQueryable<T> source)
where T: // is what?
{
if(depID > 0) { return source.Where(a => a.depID == depID); }
else return source.Where(a => a);
}
Run Code Online (Sandbox Code Playgroud)
现在我的基本问题是:我有几个表有depID - 我该如何设置Where T:
?
该方法将如何确定表是否具有depID?
解决潜在问题的更好方法?
乍一看,反应将是:创建一个界面
public interface ObjectWithDepartmentInterface {
int depID;
}
Run Code Online (Sandbox Code Playgroud)
使用此depId实现此接口的所有实体,并使用
where T : ObjectWithDepartmentInterface
Run Code Online (Sandbox Code Playgroud)
但linq to entities不接受查询中接口的属性...请参阅示例:基于接口生成的表达式
因此,唯一的方法是使用depId继承自具有depId属性的公共实体(可能是抽象)的实体.
并使用这个抽象实体作为
where T:
Run Code Online (Sandbox Code Playgroud)
更简单(但更丑陋的方式)可能是不在T上添加约束,在方法中构建谓词,并在不良情况下抛出异常.
if (typeof(T).GetProperty("depId") == null)
throw InvalidOperationException (string.Format("{0}" doesn't have a depId property, typeof(T).Name))
Run Code Online (Sandbox Code Playgroud)
编辑
但也许这不是depId作为共同财产的问题然后
public static IQueryable<T> WhereExistsOrAll<T>(this IQueryable<T> source, string propertyName, int value)
where T: // is what?
{
if (value == 0)
return source;
var parameter = Expression.Parameter(typeof(T), "m");
Expression member = parameter;
member = Expression.Property(member, propertyName);
member = Expression.Equals(member, Expression.Constant(value));
var lambda = Expression.Lambda<Func<T, bool>>(member, new[]{parameter});
return source.Where(lambda);
}
Run Code Online (Sandbox Code Playgroud)
用法
var stRecs = db.<someTable>.WhereExistsOrAll("depId", depId);
Run Code Online (Sandbox Code Playgroud)
编辑2
另一种方法是解析Predicate以获得"常量"值
类似的东西
public static IQueryable<T> GetAllOrRestrict<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate)
{
var expression = predicate.Body as BinaryExpression;
var rightPart = expression.Right as MemberExpression;
var value = GetValue(rightPart);
var test = value.ToString();
int val;
if (Int32.TryParse(value.ToString(), out val))
{
if (val != 0)
return queryable.Where(predicate);
}
return queryable;
}
private static object GetValue(MemberExpression member)
{
var objectMember = Expression.Convert(member, typeof(object));
var getterLambda = Expression.Lambda<Func<object>>(objectMember);
var getter = getterLambda.Compile();
return getter();
}
Run Code Online (Sandbox Code Playgroud)
用法
var stRecs = db.<someTable>.GetAllOrRestrict(m => m.depID == depId);
Run Code Online (Sandbox Code Playgroud)