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

时间:2014-01-02 19:38:04

标签: entity-framework entity-framework-6

我使用Entity Framework的Code First创建了我的数据库模式,其中一个模型有一个复合键(在数据库中完全反映出来)。

但是,当我尝试使用复合键列表查找记录时,我得到一个异常,说: “无法创建'匿名类型'类型的常量值。在此上下文中仅支持基本类型或枚举类型。”

这是我上次使用的代码失败了(其变体也产生了同样的错误):

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

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

1 个答案:

答案 0 :(得分:0)

编辑:重命名变量,并在多条记录上添加评论
由于这个问题的性质,我确实假设你想要一个接一个的记录。包含不能在EF中做你想做的事。

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

var record = _dataService.TableWithCompositeKey
                         .Find( Id, InstanceId )
                         .ToList();

如果您不能使用常规where子句获取记录并删除不在密钥列表中的不需要的条目,那么:

a)单独获取     的foreach ...
          发现(A,B)

b)动态构建where子句    使用像Predicate构建器这样的东西,见下面,构建where子句    同    的foreach       Thischeck =(a = X和b = Y)//例如,为(Tpoco t)创建表达式=&gt; 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);
    }
}