如何在EF6中使用复合键从表中搜索记录?

Dro*_*iss 5 entity-framework entity-framework-6

我已经使用 Entity Framework 的 Code First 创建了我的数据库模式,其中一个模型有一个复合键(这在 db 中得到了完美的反映)。

但是,当我尝试使用组合键列表查找记录时,我收到一个异常,提示:“无法创建类型为 '匿名类型' 的常量值。此上下文中仅支持原始类型或枚举类型。”

这是我最后使用的失败的代码(它的变体也产生了相同的错误):

var ids = models.Select(m => new { m.Id, m.InstanceId })
                .ToArray();

var records = _dataService.TableWithCompositeKey
                          .Where(t => ids.Contains(new { t.Id, t.InstanceId }))
                          .ToArray();
Run Code Online (Sandbox Code Playgroud)

评估记录时抛出异常。那么我怎样才能完成这样的任务呢?

phi*_*ady 0

编辑:重命名变量,并在多个记录上添加注释,
由于这个问题的性质,我确实假设您希望在另一个记录之后添加单个记录。包含无法在 EF 中执行您想要的操作。

Context.Set<poco>.Find()支持多个字段键
请参阅 Ef 源 public virtual TEntity Find(params object[] keyValues)

var record = _dataService.TableWithCompositeKey
                         .Find( Id, InstanceId )
                         .ToList();
Run Code Online (Sandbox Code Playgroud)

如果您无法使用常规 where 子句获取记录并删除不在键列表中的不需要的条目,则:

a) 单独获取 foreach...
find(a,b)

b) 使用类似于 Predicate builder 的东西动态构建 where 子句,请参阅下面,使用 foreach Thischeck = ( a = X and b = Y ) // 例如 create Expression for (Tpoco t)=>value.Equals(t .PropertyName)Whereclause.Or(thisCheck)

观察,如果您要收集的条目数量较少,那么可以考虑个人获得。如果要获取许多记录,则需要考虑生成的Where 子句的大小。这可能最终会对数据库进行全表扫描。

您还需要小心,生成的 Linq 不会导致在找到所需记录之前将所有记录加载到内存中。

这个问题没有好的解决办法。

/// See http://www.albahari.com/expressions for information and examples.
public static class PredicateBuilder
{
    public static Expression<Func<T, bool>> True<T> () { return f => true; }
    public static Expression<Func<T, bool>> False<T> () { return f => false; }

    public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                              Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
        return Expression.Lambda<Func<T, bool>>
             (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
    }

    public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
                                               Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
        return Expression.Lambda<Func<T, bool>>
             (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
    }
}
Run Code Online (Sandbox Code Playgroud)