Linq lambda 实体,不包含定义

Posted

技术标签:

【中文标题】Linq lambda 实体,不包含定义【英文标题】:Linq lambda entities , does not contain definition 【发布时间】:2013-07-09 08:06:45 【问题描述】:

我这里有这个查询代码:

//Get all records based on ActivityID and TaskID.
public IList<Model.questionhint> GetRecords1(int listTask, int listActivity)

    IList<Model.questionhint> lstRecords = context.questionhints.ToList();
    return lstRecords.GroupBy(x => new  x.QuestionNo, x.ActivityID, x.TaskID  ).Where(a => a.TaskID == listTask && a.ActivityID == listActivity).ToList(); 

错误在于.Where 语句,它说不包含ActivityIDTaskID 的定义。

完全错误:

“System.Linq.IGrouping”不包含“ActivityID”的定义,并且找不到接受“System.Linq.IGrouping”类型的第一个参数的扩展方法“ActivityID”(您是否缺少 using 指令或程序集参考?)

我的查询语句很弱,基本上我想从数据库中检索活动 id = something 和 task id = something 的记录,并按 questionNo、activityId 和 Task ID 对它们进行分组。

【问题讨论】:

顺便说一句;如果 context 这里是一个提供程序,如 LINQ-to-SQL、EF 等 - 那么IList&lt;Model.questionhint&gt; lstRecords = context.questionhints.ToList(); 是一个真的 坏主意 - 这会迫使它加载整个表,在 where 等之前 - 并切换到 LINQ-to-Objects。我已经编辑了我的答案以展示如何避免这种情况 【参考方案1】:

这里最简单的解决方法是:在分组之前过滤(哪里);这也将减少分组必须做的工作:

return context.questionhints
    .Where(a => a.TaskID == listTask && a.ActivityID == listActivity)
    .GroupBy(x => new  x.QuestionNo, x.ActivityID, x.TaskID  )
    .ToList();

如前所述,它在您的原始代码中不起作用的原因是,GroupBy 返回一个 序列 - 每个组都有一个 .Key(您的匿名类型)并且本身就是该组项的IEnumerable&lt;T&gt;序列。

但是!您的方法声称返回IList&lt;Model.questionhint&gt;;您的分组数据不是,也永远不会是IList&lt;Model.questionhint&gt; - 它将是IList&lt;IGrouping&lt;some anonymous type, Model.questionhint&gt;&gt;。所以:如果您声称它是IList&lt;Model.questionhint&gt;,那么您不能这样分组 - 由于分组是匿名类型,因此您无法更改返回类型以匹配。你有两个选择:

不要分组 按可声明的内容(自定义类型或Tuple&lt;...&gt;)分组,并将返回类型更改为匹配

例如:

public IList<IGrouping<Tuple<int,int,int>,Model.questionhint>>
        GetRecords1(int listTask, int listActivity)

    return context.questionhints
        .Where(a => a.TaskID == listTask && a.ActivityID == listActivity)
        .GroupBy(x => Tuple.Create(x.QuestionNo, x.ActivityID, x.TaskID))
        .ToList(); 

【讨论】:

@user2376998 啊;不,错误在于返回错误的数据形状 - 我将在编辑中澄清【参考方案2】:

改成Where(a =&gt; a.Key.TaskID == listTask &amp;&amp; a.Key.ActivityID == listActivity)

你正在处理一个IGrouping,它的Key属性是匿名对象new x.QuestionNo, x.ActivityID, x.TaskID

这解决了最初的错误,但现在我们尝试返回 IGroupings,它不是正确的返回类型。一种更清洁的方法是

var groups = lstRecords.GroupBy(x => new  x.QuestionNo, x.ActivityID, x.TaskID  ).Where(a => a.Key.TaskID == listTask && a.Key.ActivityID == listActivity);
IList<Model.questionhint> questionHints = new List<Model.questionhint>();
foreach(var group in groups)

    questionHints.AddRange(group);

return questionHints;

请注意,此代码未经测试。您可以在一行 linq 中完成所有这些操作(我确信 Mark 会这样做),但是为了便于阅读,我倾向于将其拆分

替代方案

如果您的目标是获取所有符合条件的 questionHint,那么简单的 Where 子句有什么问题?

lstRecords.Where(a=>a.TaskID == listTask && a.ActivityID == listActivity).ToList();

参考文献http://msdn.microsoft.com/en-us/library/bb344977.aspx

【讨论】:

感谢您的快速回复,在完成上述操作后我遇到了这个错误:无法隐式转换类型'System.Collections.Generic.List>' 到 'System.Collections.Generic.IList'。存在显式转换(您是否缺少演员表?) 问题是 Where 子句返回一个 IEnumerable> (忽略类型)。 IGrouping 是 IEnumerable,但即使我们将其简化为 IEnumerable,您也需要在返回之前将它们全部聚合在一起。这将暂时解决问题,但它远非最有效的方式(或可读方式)。 这是因为我的数据库有许多属于同一个 questionNo、taskid 和 activityid 的记录,所以我需要对它们进行分组以便将它们分开。 ***.com/questions/17584451/…这是我的桌子 如果您希望将它们分组,则不能返回 IList。如果你想在之后将它们分开,请在返回此函数后将它们分组。否则将失去对它们进行分组的努力(当您将它们作为列表返回时再次取消组合)

以上是关于Linq lambda 实体,不包含定义的主要内容,如果未能解决你的问题,请参考以下文章

使用 Func<T, string> lambda 动态构造 where 子句 - linq 到实体

是否可以将 Linq 中的 lambda 参数化为实体选择

使用实体框架 4.1 进行多表连接,我应该使用 lambda 还是 LINQ?

帮助我使用实体框架从 SQL 转换为 linq 嵌套 lambda 表达式

用于从实体类及其导航属性中选择多个列的 Linq Lambda 表达式

缺少实体框架包含(lambda)扩展