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