9

我经常有这样的代码:

var stRecs = db.<someTable>
             .Where(a => a.DepID == depID)

选择一条记录,但是如果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);
}

现在我的基本问题是:我有几个带有 depID 的表 - 如何设置Where T:
该方法将如何确定表是否具有 depID?

解决潜在问题的更好方法?

4

5 回答 5

6

乍一看,反应是:创建一个接口

public interface ObjectWithDepartmentInterface {
    int depID;
}

使所有使用此 depId 的实体实现此接口,并使用

where T : ObjectWithDepartmentInterface

但是 linq to entity 不接受查询中接口的属性...参见例如:基于接口生成的表达式

因此,唯一的方法是使您的实体具有从具有 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 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);
}

用法

var stRecs = db.<someTable>.WhereExistsOrAll("depId", depId);

编辑 2

另一种方法是解析谓词以获得“常量”值

类似的东西

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();
}

用法

var stRecs = db.<someTable>.GetAllOrRestrict(m => m.depID == depId);
于 2013-05-24T08:46:46.983 回答
2

I know it's not particularly fashionable, but isn't this exactly what the Query Builder methods in Entity Framework are for?

var stRecs = db.<someTable>
             .Where("it.DepID == @depID OR @depID = 0", 
                    new ObjectParameter("depID", depID));

This works on any someTable such that it has a column named DepID. It can of course be made an extension method:

public static ObjectQuery<T> WhereIdEqualOrAll<T>(this ObjectQuery<T> q, int depID)
    where T : class
{
    return q.Where("it.DepID = @id OR @id = 0", new ObjectParameter("id", id));
}

to be invoked thus:

var stRecs = db.<someTable>.WhereIdEqualOrAll(depID);
于 2013-05-24T09:12:38.723 回答
1

使用接口:

public interface IInterface
{
   int depId;
}

这将强制T继承IInterface和实施depId.

然后你可以将它添加到扩展中:

public static IQueryable<T> WhereDepID_OrAll<T>(this IQueryable<T> source) where T: IInterface
{

}
于 2013-05-24T08:46:32.917 回答
0

Raphaels Edit 2 完成了这项工作!

小型版:如果存在 DepID,我如何包含 NULL 值?

我喜欢返回 ID == x OR ID == NULL 的所有部门

也许还有一个额外的 bool includeNullValues)

public static IQueryable<T> GetAllOrRestrict<T>(this IQueryable<T> queryable,
 Expression<Func<T, bool>> predicate, 
 bool includeNullValues)
    {
        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)
            {
                if (includeNullValues)
                {
                    var parameter = Expression.Parameter(typeof(T),"m");

                    return queryable.Where(predicate) <====HOW to " || depID == null) ???
                }
                else
                {
                return queryable.Where(predicate);
                }
            }
        }

        return queryable;
    }
于 2013-05-24T10:31:11.950 回答
0

使用接口,然后手动构建表达式树,引用实际的类。

于 2013-05-24T08:55:37.957 回答