【问题标题】:Linq expression (containing OR) incorrectly calculating WHERE clause?Linq 表达式(包含 OR)错误地计算 WHERE 子句?
【发布时间】:2014-04-18 21:14:50
【问题描述】:

我有一个奇怪的情况,我找不到 Linq 2 实体查询不返回结果的方法。

第一个查询返回结果,但第二个没有返回结果。

summaryData = db.PromoSummary.Where(x => x.Month == state.OldPromoStart.Month).ToList();
summaryData = db.PromoSummary.Where(x => (x.Month == state.OldPromoStart.Month) | (x.Month == state.OldPromoEndMonthMax)).ToList();

如果“A”为真,那么“A or B”也应该为真...(在这种情况下,第一个语句为真,所以无论第二个语句如何,它都应该返回结果,对吧?)

附: db 是 DbContext,PromoSummary 是 DbSet

任何想法我做错了什么?

编辑

此 PromoSummary DbSet 包含 Month==9 的行,但没有 Month == 10 的行。我更改了 |到||,但结果是一样的——第一个查询返回结果,但第二个查询返回0条记录...

summaryData = db.PromoSummary.Where(x => x.Month == 9).ToList();
summaryData = db.PromoSummary.Where(x => (x.Month == 9) || (x.Month == 10)).ToList();

编辑#2

我想这就是 Andrew 的建议……为什么要进行“不为空”检查? 附:在数据库中的 Month 属性称为 SummaryMonth(使用 Fluent api 定义)还有一件事 - 此属性的类型为 byte

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[CustomerId] AS [CustomerId], 
[Extent1].[SummaryYear] AS [SummaryYear], 
[Extent1].[SummaryMonth] AS [SummaryMonth], 
[Extent1].[ThemeId] AS [ThemeId], 
[Extent1].[CurrentStateId] AS [CurrentStateId]
FROM [PromotionSummary] AS [Extent1]
WHERE ((9 = ( CAST( [Extent1].[SummaryMonth] AS int))) 
         AND ( CAST( [Extent1].[SummaryMonth] AS int) IS NOT NULL)) 
   OR ((10 = ( CAST( [Extent1].[SummaryMonth] AS int))) 
         AND ( CAST( [Extent1].[SummaryMonth] AS int) IS NOT NULL))

【问题讨论】:

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


    【解决方案1】:

    您应该使用|| 而不是按位或|

    对于您的第二次更新,请尝试使用以下代码:

    List<byte> months = new List<byte> {9, 10};
    
    summaryData = db.PromoSummary.Where(x => months.Contains(x.Month)).ToList();
    

    【讨论】:

    • 你可以在不执行第一个查询的情况下执行第二个查询吗?结果不一样吗?
    • 第二个查询生成的命令文本是什么?你能看看你的 ObjectQuery 吗?
    • 请查看第二个编辑 - 我从调试中获取了该查询 -> var q = db.PromoSummary.Where(x => (x.Month == 9) || (x.Month == 10)); //然后复制q.InternalQuery
    • 你能看看当你使用类似x.Month == (byte)9...btw时再次生成的查询,我会考虑使用int值类型而不是byte
    • 您能否尝试从我的答案编辑中查询?您的提供商可能在处理字节参数时遇到了一些麻烦。或者实体框架本身存在一些问题...请参阅此处接受答案的最后评论:stackoverflow.com/questions/5627670/…
    【解决方案2】:

    您应该使用|| 运算符而不是|

    summaryData = db.PromoSummary.Where(x => (x.Month == state.OldPromoStart.Month) || (x.Month == state.OldPromoEndMonthMax)).ToList();
    

    | 运算符是二元 OR,但 || 是逻辑运算符。

    【讨论】:

      【解决方案3】:

      因为您的 OR 是 Binary OR

      你应该这样写:

      db.PromoSummary.Where(x => (x.Month == state.OldPromoStart.Month) 
             || (x.Month == state.OldPromoEndMonthMax)).ToList();
      

      编辑

      考虑到这个可能是 SQL 驱动问题,你可以尝试做这样的事情。 LINQ 以延迟执行着称,所以你可以这样写:

      var first =  db.PromoSummary.Where(x => (x.Month == state.OldPromoStart.Month));
      var second=  db.PromoSummary.Where(x => (x.Month == state.OldPromoEndMonthMax));
      
      first.AddRange(second);     
      return first.FirstOrDefault();
      

      应该生成你正在搜索的SQL,所以也产生了理想的结果。

      【讨论】:

      • 你连接到 MS Sql Server 了吗?
      • 不是VistaDB,有关系吗?
      • 很可能(粗体)有一个驱动程序“问题”,无法将您的查询转换为有效的 SQL。
      • 各位,让 OP 看看生成的 CommandText,接下来调用 ToTraceString() 看看实际的事务 sql
      • 请看一下,我在第二次编辑中用一些 cmets 添加了 SQL 语句
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-02
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      • 2021-05-16
      相关资源
      最近更新 更多