【问题标题】:How to use two conditions in Linq lambda which has different where clause如何在具有不同 where 子句的 Linq lambda 中使用两个条件
【发布时间】:2012-01-01 00:13:18
【问题描述】:

我想在表 Items 中查询我的项目,其中每个项目的最后一次更新必须小于 91 天(从最后一次更新到现在)并且数量 > 0。 这是我在模型中的代码:

public IList<Item> GetAllProducts()
{
 var ien_item = from i in this.DataContext.Items  
 orderby i.LastUpdated descending
 select i;
 return ien_item.ToList().Where(
                 s =>
                 HelperClasses.HelperClass.IsLastUpdate(s.LastUpdated.Value) == true 
                 && 
                 (s => s.Quantity) > 0
                 )
                 .ToList();

}

谁能解决?谢谢。

【问题讨论】:

  • 究竟解决什么问题?您已经提供了一些代码 - 它有效吗?请注意,ToList() 意味着您的查询将完全在客户端执行,这对我来说似乎是个坏主意……但假设您对此感到满意,那么有什么不工作?
  • @Jon Skeet:我的查询似乎出现错误,但我不知道如何更正。
  • 您到底想解决什么问题?您的查询看起来不错,除了“&& (s => s.Quantity) > 0”,您可以只使用“&& s.Quantity > 0”
  • @socheata:“似乎出现错误”是什么意思?如果您遇到错误,您应该告诉我们那是什么错误。请阅读tinyurl.com/so-hints - 您提供的有关问题所在的信息越多,我们就越有可能提供帮助。
  • 请将您的错误信息添加到问题中。

标签: c# asp.net asp.net-mvc


【解决方案1】:

简单...

public IList<Item> GetAllProducts()
{
     var ien_item = 
          from i in DataContext.Items
          where 
               HelperClasses.HelperClass.IsLastUpdate(i.LastUpdated.Value)
               && s.Quantity > 0
          orderby i.LastUpdated descending
          select i;

     return ien_item.ToList();
}

Linq to SQL:不允许使用方法(linq 不是魔术,不能将 C# 方法转换为 TSQL)
http://msdn.microsoft.com/en-us/library/bb425822.aspx

Linq to Object:虽然看起来一样,但比 linq to SQL 强大得多...但不能查询 SQL 数据库:)
http://msdn.microsoft.com/en-us/library/bb397919.aspx

Linq to XML:与 linq to Object 相同,带有 xml 对象
http://msdn.microsoft.com/en-us/library/bb387098.aspx

Linq to Dataset:与 Linq to SQL 不同!
http://msdn.microsoft.com/en-us/library/bb386977.aspx

其他 linq 提供者:
http://en.wikipedia.org/wiki/Language_Integrated_Query

【讨论】:

  • IsLastUpdated()的方法是: public static bool IsLastUpdate(DateTime dt) { bool _isLastUpdate = false; DateTime _today = DateTime.Now;时间跨度 _timespan = _today.Subtract(dt); _isLastUpdate = (Convert.ToInt32(string.Format("{0:00}", _timespan.TotalDays)) code
  • 这是我想要的细节: 1. If(lastUpdated >=91 && quality==91 && quality 91 && quality = 0){//item not show}。 4. if(lastUpdated>91 && Quality >0){//item show}.
  • 不,在“Linq to objects”中使用方法不是错误。虽然使用“Linq to SQL”中的方法是错误的。在“Linq to XML”中使用方法也不是错误。在您的示例中,您使用的是“Linq to objects”而不是“Linq to SQL”。
【解决方案2】:

问题在于您的 lambda 语法。您正在尝试在定义第一个 lambda 的过程中定义第二个 lambda。虽然这是可能的,并且在某些情况下很有用,但它是一种高级场景,在您知道自己需要它之前可能对您没有用处。

现在,你不需要它。除非你知道你需要它,否则你不需要它:)

所以-

而不是你写的:

.Where(
    s =>
        HelperClasses.HelperClass.IsLastUpdate(s.LastUpdated.Value) == true 
            && (s => s.Quantity) > 0
    )

改为这样写:

.Where(
    s =>
        HelperClasses.HelperClass.IsLastUpdate(s.LastUpdated.Value) == true 
            && s.Quantity > 0 // Notice I got rid of the extra lambda here
    )

如果你有病态的好奇:

你得到的编译错误是因为你没有正确定义你的第二个 lambda。它重新定义了一个您已经使用过的变量 (s),并且您试图检查 lambda 是否大于零。这是没有意义的。您只能将 lambda 的 result 与某个值进行比较。这就像调用一个函数。您不会将函数与数字进行比较 - 您将调用函数时获得的结果与数字进行比较。

【讨论】:

  • 没有承诺这会解决所有问题,但这是一个对我来说很明显的错误,并且出现此错误会破坏您的代码。如果还有更多问题,请继续提供信息 :) 并提供完整的错误消息(将它们添加到问题中)
  • 我的 lambda 的描述:该项目将不再显示在我的页面中,如果:每个项目的最后一次更新 = 91 天前(从上次更新到现在),并且质量 = 0。但是如果质量 = 0 且每个项目的最后一次更新
  • @socheata:这不是这个问题的一部分,所以你真的应该发布另一个问题(或者只是学习布尔逻辑)。但无论如何我会尽力提供帮助。您的 where 子句应与您的“项目仍将显示在页面中”逻辑相匹配。所以你想要Where(s =&gt; DateTime.Today - s.LastUpdated.Date &lt;= TimeSpan.FromDays(91) &amp;&amp; s.Quantity == 0)
  • @socheata:如果您已经解决了编译器错误,并且之前的评论没有帮助,那么请发布另一个问题。这是一个单独的问题。
【解决方案3】:

我们真的不知道这里有什么问题。编辑:梅林发现了它;你的 lambda 语法搞砸了。不过这里还有更多工作要做。

但是,我认为你会想要这个:

public IList<Item> GetAllProducts()
{
     var lastUpdateLimit = DateTime.UtcNow.Date.AddDays(-91);
     var query = from item in DataContext.Items
                 where item.Quantity > 0 && item.LastUpdated >= lastUpdateLimit
                 orderby item.LastUpdated descending
                 select item;
     return query.ToList();
}

请注意,这能够在数据库端进行所有查询,而不是在客户端获取所有项并进行过滤。它确实假设HelperClasses.HelperClass.IsLastUpdate 很简单,并且基本上等同于我上面的过滤器。

(另外需要注意的一点是,通过评估UtcNow.Date一次,所有项目的结果将是一致的 - 而如果您的代码在每次调用 IsLastUpdate 时评估“今天”,由于查询正在评估时的时间进展,查询中的某些值最终可能会根据与其他值不同的日期被过滤。)

编辑:如果您真的需要使用HelperClasses.HelperClass.IsLastUpdate,那么我建议:

public IList<Item> GetAllProducts()
{
     var query = from item in DataContext.Items
                 where item.Quantity > 0
                 orderby item.LastUpdated descending
                 select item;
     return query.AsEnumerable()
                 .Where(s => HelperClass.IsLastUpdate(s.LastUpdated.Value))
                 .ToList();
}

...那么至少数量过滤器是在数据库端执行的,并且您没有在需要之前创建完整的缓冲列表(注意对ToList 的单个调用)。

【讨论】:

  • 感谢 Jon Skeet,它不能像这样查询,因为 LastUpdated 必须由我的 Helper 类中的方法 isLastUpdate() 限定,所以我不能在查询中使用此方法。
  • @socheata:那个方法做了什么?如果您可以在查询中表达该逻辑以便它可以在服务器端执行,那么效率会高得多。基本上我担心你在这里没有给我们足够的信息 - 我写了一个查询匹配你的描述“每个项目的最后更新必须少于 91 天”。 IsLastUpdated 有没有更多的逻辑?
  • 如果我只写,这个查询可以完美运行:codereturn ien_item.ToList().Where(s => HelperClasses.HelperClass.IsLastUpdate(s.LastUpdated.Value) == true).ToList ();但是当我添加关于数量的条款时,它会出错。
  • @socheata:“它错误”不是很具有描述性。错误是什么?请阅读我链接到的文章。
  • @socheata:真的不应该 - 你确定你没有在某处更改我的查询吗?你也确定你没有混淆质量和数量吗?您已经在不同的地方使用了这两个术语。我给出的两个查询 will 过滤掉数量为 0 的项目。实际上并不清楚你看到了什么,因为你的最后一条评论似乎自相矛盾 - 首先你说这些项目没有t显示,然后他们做...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多