我使用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();
评估记录时抛出异常。那我怎么能完成这样的任务呢?
答案 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);
}
}