c# - 消除循环并改用 Linq

标签 c# linq entity-framework foreach

假设我有一个列表如下:

 List<R> lstR = GetR();

现在我想要一个 Linq 语句来获取分配给 R 的菜单,我通过使用循环然后使用 Linq 获取菜单来实现这一点,如下所示:

 List<int> ids = new List<int>();
 foreach (R r in lstR)
 {
   ids.Add(r.Id);
 }

 menu = (from s in db.Menu
         where ids.Contains(s.R.Id)
         select s.MenuText).Distinct();

现在据我所知上面是两个循环(Linq 使用内部循环)。我能否将这两个语句结合起来,即不执行第一个循环来获取 ID?

最佳答案

在两个lstRdb.Menu是内存数据集 (Linq-to-Objects) 或 IQueryable从你的数据库中收集,你可以这样做:

menu = 
    (from s in db.Menu
     where lstR.Select(r => r.Id)
               .Contains(s.R.Id)
     select s.MenuText)
    .Distinct();

或者这个:

menu = 
    (from s in db.Menu
     join r in lstR on s.R.Id equals r.Id
     select s.MenuText)
    .Distinct();

但是,由于 List<R>存在于内存中并且 db.Menu是一个 IQueryable ,你的选择是有限的。你可以实现 db.Menu进入 IEnumerable ,所以你可以在内存中处理它:

List<R> lstR = GetR();
menu = 
    (from s in db.Menu.AsEnumerable()
     join r in lstR on s.R.Id equals r.Id
     select s.MenuText)
    .Distinct();

但是,如果有很多记录,这可能会很昂贵。最好做这样的事情,诚然,这看起来与您已经拥有的并没有太大不同:

List<R> lstR = GetR();
var ids = lstR.Select(r => r.Id).ToList(); // or .ToArray();
menu = 
    (from s in db.Menu
     where ids.Contains(s.R.Id)
     select s.MenuText)
    .Distinct();

但事实上,最好的选择是看看你是否可以重构 GetR以便它返回 IQueryable<R>从你的数据库。这样您就可以同时使用前两个选项,而无需先将任何集合具体化到内存中。顺便说一下,一旦你完成了 设置导航属性,你就可以做这样的事情:

IQueryable<R> lstR = GetR();
menu = 
    (from r in lstR
     from s in r.Menus
     select s.MenuText)
    .Distinct();

关于c# - 消除循环并改用 Linq,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18768447/

相关文章:

c# - 更改命名空间导致的错误?

c# - 从 CLR 样式的类型全名获取 C# 样式的类型引用

javascript - MVC 中的用户代码未处理 HTTP 异常

c# - LINQ 中的时区转换

c# - 如何将具有前端 SPA 的 Azure CDN 和具有 .Net Core WebApi 的 Azure WebApp 配置到同一自定义域?

c# - 这行是做什么的,我应该从哪个方向读取三元运算符?

c# - 重构 OrderBy 表达式

c# - Xlinq 查询返回 nullWhereEnumerableIterator<>

c# - 不同组按特定顺序的组合

c# - Entity Framework 审计一对多关系并捕获相关实体