【问题标题】:LINQ Filter List inside another LINQ Query另一个 LINQ 查询中的 LINQ 筛选器列表
【发布时间】:2013-07-26 01:26:23
【问题描述】:

好的,所以我有一个看起来像这样的模型:

public int idA
public int idB
public int total

public virtual TableA TableA { get; set; }
public virtual TableB TableB { get; set; }

表 A 和 B 的模型彼此相似,它们都通过类似的方式与此相关

public virtual List<Association> Assocation { get; set; }

我现在正在尝试查询它,它正在工作,但我希望能够在 idB 等于某个整数时过滤结果,例如:

var results = db.TableA
                .Where(t => t.idA == id)
                .Where(t => t.Association.Where(m => m.idB == 1));

这会返回以下异常:

不能隐式转换为 'bool' 无法将 lambda 表达式转换为委托类型“System.Func”,因为块中的某些返回类型不能隐式转换为委托返回类型

非常感谢您的帮助!

更新

所以我实现了以下内容:

var results = db.TableA
                .Where(t => t.idA == id)
                .Where(t => t.Association.Any(m => m.idB == 1));

由于此关联表使用复合主键,因此应该只返回 1 个结果。大约有 200 个结果与给定的 t.idA == id 匹配,这就是我要返回的结果。它不仅返回 1 个结果。

为了完整起见,这里是正在创建的查询,我省略了字段本身以简化一些:

SELECT ... fields here ...
WHERE ([Extent1].[id] = @p__linq__0) AND (@p__linq__0 IS NOT NULL) 
AND ( EXISTS (SELECT ... fields here ....
                WHERE ([Extent1].[id] = [Extent2].[idA]) AND (1 = [Extent2].[idB])
              )
     )

更新 2

所以 .Any() 的问题是,如果它包含一个匹配 1 的值,它将返回整个集合,我想要的只是返回匹配 1 的值。因此,我唯一要做的就是可以想到的做法是取出多余的 118 行,然后过滤返回的列表。幸运的是,在进行分析时,这并没有像我最初预期的那样影响 SQL 服务器,因此没有必要进行预优化。但是,如果有人确实知道如何使用 LINQ 在初始 SQL 查询中过滤列表,我仍然很想知道,因为我确信我可以在将来对数据库的影响可能更严重的情况下使用它,因此优化保证。

【问题讨论】:

  • 你有什么问题?错误信息很清楚:t =&gt; t.Association.Where(m =&gt; m.idB == 1) 必须返回一个布尔值,但t.Association.Where(m =&gt; m.idB == 1) 不是布尔值。

标签: c# .net linq entity-framework-4


【解决方案1】:

'.Where' lambda 函数需要返回一个布尔值。目前,您正在针对另一个记录集返回“.Where”的结果。相反,您可能打算这样:

var results = db.TableA
                .Where(t => t.idA == id)
                .Where(t => t.Association.Any(m => m.idB == 1));

如果 't.Association' 包含任何符合条件的记录,'.Any' 函数将返回 true。

【讨论】:

  • 是的,我明白这一点,但我想要的是它只返回匹配的 1 个值,而不是简单地告诉我该列表确实包含我正在寻找的值。感谢您的意见。
【解决方案2】:

我认为你想要做的是使用Any 方法。像这样的东西应该可以工作:

var results = db.TableA
                .Where(t => t.idA == id)
                .Where(t => t.Association.Any(m => m.idB == 1));

这将返回任何TableidA 等于id 并且至少在AssociationidB 等于1。

或者,如果您更喜欢查询语法:

var results = 
    from a in TableA
    where a.idA == id && a.Association.Any(m => m.idB == 1)
    select a;

【讨论】:

  • 由于某种原因,它仍然返回 118 个结果(全部),包括等于 1 的结果和其他结果。有什么想法吗?
  • @coldcoder 请更新您的问题以包含您的预期和实际结果。
  • 第二个代码将是 OP 想要的,恭喜!我认为第二个会更好,但它仍然会导致返回超过 1 个项目?
【解决方案3】:

这应该可行:

var results = db.TableA
    .Where(t => t.idA == id)
    .Select(t => new {
        Item = t
    ,   AssociatedItem = t.Association.SingleOrDefault(m => m.idB == 1)
    })
    .Where(p => p.Associated != null)
    .ToList();

此代码生成具有两个字段的匿名类型对象列表 - 带有项目的 Item 字段和包含其关联项目的 AssociatedItem 具有 idB1

注意,以上代码假设与idBidB 的关联项最多有一个1;否则,SingleOrDefault 会失败。

【讨论】:

  • 谢谢,这就是我想要的——很像 LINQ to SQL 连接。让我省了很多麻烦!
猜你喜欢
  • 2011-09-11
  • 1970-01-01
  • 2017-05-06
  • 2017-03-20
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多