【问题标题】:Refactoring linq-to-sql method that returns matched values重构返回匹配值的 linq-to-sql 方法
【发布时间】:2013-02-05 14:15:11
【问题描述】:

我有一个简单的 linq-to-sql 语句,它将 string[] 中的值与表中的值匹配并返回匹配的表值。

_table 的类型为 System.Data.Linq.Table<TEntity>

public IEnumerable<ZipCode> match(IEnumerable<string> values) {
    HashSet<string> valueSet = new HashSet<string>(values);
    return _table.Where(x => valueSet.Contains(x.zipcode);
}

我怎样才能重构它,以便我可以将要使用的字段传递给Contains()

我的失败尝试:

public IEnumerable<ZipCode> match<T>(IEnumerable<T> values, 
        Expression<Func<ZipCode, T>> field) {
    HashSet<T> valueSet = new HashSet<T>(values);
    return _table.Where(x => valueSet.Contains(field(x)));
}

这会产生错误:

方法 'System.Object DynamicInvoke(System.Object[])' 不支持 SQL 转换。

我的想法是我可以使用表达式树来为Contains() 提供字段,但对如何使用表达式或者这是否是使用表达式的正确方法感到困惑。可能有更好的解决方案。

【问题讨论】:

  • 这被标记为linq-to-sql - 你是说linq吗?
  • 我会在我的问题中详细说明... _table 是System.Data.Linq.Table

标签: c# linq linq-to-sql refactoring


【解决方案1】:

我能够使用以下内容(在 .NET 4.5 中,但我相信它可以在早期版本中使用)

static IEnumerable<TTable> Match<TTable, TField>(IQueryable<TTable> table, IEnumerable<TField> values, Expression<Func<TTable, TField>> fieldSelector)
{
    var valuesConstant = Expression.Constant(values.Distinct());

    var callContains = Expression.Call(typeof(Enumerable), "Contains", new[] { typeof(TField) }, new Expression[] { valuesConstant, fieldSelector.Body });

    var whereExpression = Expression.Lambda<Func<TTable, bool>>(callContains, (fieldSelector.Body as MemberExpression).Expression as ParameterExpression);

    return table.Where(whereExpression);
}

您应该可以删除我使用的表参数并使用您拥有的成员变量。

【讨论】:

    【解决方案2】:

    Func&lt;ZipCode, T&gt; field代替Expression&lt;Func&lt;ZipCode, T&gt;&gt; field

    public IEnumerable<ZipCode> match<T>(IEnumerable<T> values, Func<ZipCode, T> field)
    {
        HashSet<T> valueSet = new HashSet<T>(values);
        return _table.Where(x => valueSet.Contains(field(x)));
    }
    

    【讨论】:

    • 这会给出错误“方法 'System.Object DynamicInvoke(System.Object[])' 没有支持的 SQL 转换。”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多