【问题标题】:Linq Conversion From ICollection<T> to List<T>从 ICollection<T> 到 List<T> 的 Linq 转换
【发布时间】:2014-07-02 20:40:11
【问题描述】:

我正在使用 Code First 实体框架。

我正在使用以下简单的类:

public class Users
{
    public ICollection<Projects> Projects{get;set;}
}

public class Projects
{
    public ICollection<Users> Users{get;set;}
}

我正在使用 linq 进行数据检索。执行以下查询时:(注意lstProjectsList&lt;Project&gt;

var lstUsers = (from users in lstProjects
                where users.ProjectId == pId
                select users.Users).ToList();

我有一个List&lt;Users&gt; 对象并想用项目填充此列表。喜欢,

var lstUsersToDisplay = new List<Users>();
lstUsersToDisplay = (List<Users>)lstUsers; //This can't be cast.

ICollection&lt;T&gt; 转换为List&lt;T&gt; 的方法是什么?

其次,我有List&lt;Users&gt; 并想将其转换为ICollection&lt;Users&gt; 如何实现?

已编辑: 情景,更清楚的是 所有Projects 都加载到lstProjects 中,我们需要选择映射到特定项目的Users。这些用户也包含在Projects 中作为集合。每个Project 都有它的Users collection,就像我分解 lstProjects 一样:

lstProjects --> [0]-->//other Properties ICollection[Users]-->[0]//Contains User class Properties [1].... [1] ... same procedure

希望它清除场景

【问题讨论】:

  • 什么是lstProjects?如果是List&lt;Project&gt;,那么您实际上得到了List&lt;Project&gt; 作为lstUsers,尽管您的名字。如果在 Visual Studio 中将鼠标悬停在 var lstUsersvar 上,它会显示什么?错误信息是什么?如果您展示一个简短但完整的程序来演示该问题,那将真的有所帮助。 (另外,你为什么要创建一个空列表然后忽略它?为什么不直接使用var lstUsersToDisplay = lstUsers;?)
  • @JonSkeet 我在键入时表示歉意,基本上我正在从项目列表中检索用户集合。我已经修改了
  • 所以您的users 范围变量实际上是Project?神圣的混乱命名,蝙蝠侠!听起来您现在有了List&lt;ICollection&lt;Users&gt;&gt;。同样,您应该将鼠标悬停在 var 上以查看您实际拥有的内容...

标签: c# linq entity-framework linq-to-entities icollection


【解决方案1】:

如果您的查询是真正这个:

var lstUsers = (from users in lstProjects
                where users.ProjectId == pId
                select users.Users).ToList();

那么这就相当于:

List<ICollection<Users>> lstUsers = (from users in lstProjects
                                     where users.ProjectId == pId
                                     select users.Users).ToList();

如果您尝试从 单个 项目中获取使用列表,我会将其写为:

var lstUsers = lstProjects.Single(project => project.ProjectId == pId)
                          .Users
                          .ToList();

如果可能有多个项目具有相同的ProjectId,您希望扁平化用户。例如:

var lstUsers = lstProjects.Where(project => project.ProjectId == pId)
                          .SelectMany(project => project.Users)
                          .ToList();

或者在查询表达式语法中:

var lstUsers = (from project in lstProjects
                where project.ProjectId == pId
                from user in project.Users
                select user).ToList();

请注意,我的范围变量称为project,因为它指的是一个项目,不是一个用户。命名很重要——注意它。我还将ProjectsUsers 类型重命名为ProjectUser,假设它们实际上只代表一个实体。

【讨论】:

  • “或查询表达式语法”中是否应该有WHERE?
  • 很好 - 但是你为什么不使用.Sinlge 的重载来过滤你的第三个sn-p?恕我直言,它看起来更好,更易读?
  • @bdimag:嗯,是的。会修复的。
【解决方案2】:

lstUsers 不是List&lt;User&gt;。这是List&lt;ICollection&lt;User&gt;&gt;。您将每个项目映射到一个序列用户,而不是单个用户。要将集合集合展平为仅包含内部项目的集合,您可以使用 SelectMany,或者,在查询语法中,您可以这样写出查询:

var lstUsers = (from project in lstProjects
                where project.ProjectId == pId
                from user in project.Users
                select user).ToList();

现在你有一个List&lt;User&gt; 用于lstUsers。您可以将其原样分配给 List&lt;User&gt;ICollection&lt;User&gt;

【讨论】:

    【解决方案3】:
    using System.Linq; //include extension method OfType<> for ICollection
    ...
    List<Projects> userList = lstUsers.OfType<Projects>().ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多