【问题标题】:Optimal LINQ filtering method最优 LINQ 过滤方法
【发布时间】:2017-08-02 08:23:54
【问题描述】:

我正在过滤 LINQ 中项目列表的结果,我已经看到了两种方法,想知道哪种(如果有的话)更好。一个是我在玩了Intellisense之后想出的方法,另一个来自ASP.NET MVC教程(found here

我的方法

    // GET: ProductVersions
    public ActionResult Index(string productName)
    {
        var productVersions = db.ProductVersions.Include(p => p.LicenceVersion).Include(p => p.Product);

        if (!string.IsNullOrEmpty(productName))
        {
            productVersions = productVersions.Where(s => s.Product.Name == productName);
        }

        return View(productVersions.ToList());
    }

教程方法

public ActionResult Index(string movieGenre)
{
    var GenreLst = new List<string>();

    var GenreQry = from d in db.Movies
                   orderby d.Genre
                   select d.Genre;

    GenreLst.AddRange(GenreQry.Distinct());
    ViewBag.movieGenre = new SelectList(GenreLst);

    var movies = from m in db.Movies
                 select m;

    if (!string.IsNullOrEmpty(movieGenre))
    {
        movies = movies.Where(x => x.Genre == movieGenre);
    }

    return View(movies);
}

我的问题

  1. 性能是否存在显着差异,尤其是第二个选项非常冗长时
  2. 使用我的方法是否有我遗漏的风格约定
  3. 使用第二种方法是否还有其他可能的优势

~编辑~

原来我需要 ViewBag 数据才能在前端填充下拉过滤器(更遗憾的是),所以我的实际代码如下:

        // GET: ProductVersions
        public ActionResult Index(string productName)
        {
            //Get list of product names to filter by
            var ProductLst = new List<string>();
            var ProductQry = from pv in db.ProductVersions
                             orderby pv.Product.Name
                             select pv.Product.Name;

            ProductLst.AddRange(ProductQry.Distinct());
            ViewBag.productName = new SelectList(ProductLst);

            //Populate product versions
            var productVersions = db.ProductVersions.Include(p => p.LicenceVersion).Include(p => p.Product);

            //Filter by product name
            if (!string.IsNullOrEmpty(productName))
            {
                productVersions = productVersions.Where(s => s.Product.Name == productName);
            }

            return View(productVersions.ToList());
        }

【问题讨论】:

  • 你问的是from x in db.Something select x还是简单的db.Something.AsQueryable()
  • 是的,还有 GenreLst 和 GenreQry 的好处。我知道在我的示例中我没有添加到 viewbag 中,但除此之外......
  • @JLewis 只是为 UI 的另一部分填充数据。如果您没有另一块 UI 来获取数据:那就太好了!
  • 原来我确实需要 viewbag 数据来过滤下拉列表。 叹息
  • @J Lewis 看看我的回答。重构和惰性是重要的主题

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


【解决方案1】:

只有示例代码的最后一部分可以与您的问题相媲美 - 流派列表是 UI 中的其他内容,您的代码中没有,这很好。所以我们比较的是:

var productVersions = db.ProductVersions.Include(p => p.LicenceVersion)
     .Include(p => p.Product);

if (!string.IsNullOrEmpty(productName))
{
    productVersions = productVersions.Where(s => s.Product.Name == productName);
}

return View(productVersions.ToList());

var movies = from m in db.Movies
             select m;

if (!string.IsNullOrEmpty(movieGenre))
{
    movies = movies.Where(x => x.Genre == movieGenre);
}

return View(movies);

它们实际上是相同的 - 主要区别在于您的代码中包含额外的内容,如果您需要它们也可以。

它们是如此具有可比性,以至于在比较方面没有什么可以谈论的。

我个人更喜欢您示例中的ToList(),因为它强制数据在控制器而不是视图中实现。与之相反的是,让视图具有 queryable 允许视图进一步组合它。我不希望我的观点构成查询,但这是一个风格点。

【讨论】:

  • 我也试图避免我的观点有任何类型的处理,所以很高兴知道这一点。我会给它一点时间,但这是一个很好的答案:)
【解决方案2】:

您提供的代码示例存在很大差异,但假设您询问的是扩展方法语法与查询语法,我认为答案如下:

  1. 性能没有差异。编译器对样本的处理方式相同。
  2. 您没有遗漏任何风格惯例。我通常发现链接扩展方法更具可读性和可维护性
  3. 当您想利用多个范围变量时,可以使用查询语法。看看这个答案: LINQ - Fluent and Query Expression - Is there any benefit(s) of one over other?

【讨论】:

  • 我认为这个作者示例和关于 Eager 和 Lazy 的教程示例之间存在巨大差异 :) 在实时工作中,您可以检测到这一点。 :)
  • 你是对的,有很多不同之处。我只是从他提出问题的方式假设他有兴趣了解扩展方法语法与查询语法之间的区别。
【解决方案3】:

我了解到您使用的是 Eager Loading。我认为如果您的模型不是那么复杂,则不需要 EagerLoading。 出于这个原因,使用 Layz 加载;我也尝试重构你的代码。看看我的代码风格和代码行数 :) 这对你特别大的类有帮助 :) H

http://www.entityframeworktutorial.net/EntityFramework4.3/lazy-loading-with-dbcontext.aspx

在下面的链接你可以得到详细的信息。

示例类也可以翻译linke this

public ActionResult Index(string productName)
{
   if(string.IsNullOrEmpty(productName)) return View(new List<ProductVersions>());
   return View(db.ProductVersions.Where(s => s.Product.Name == productName).ToList());
}

最后,“你的经验和教程”之间的压缩是错误的。因为在 TutorialExp 中使用了 ViewModel。这对于防止客户端直接使用 DbCon 对象很有用。在我看来

using(var db=new DbEntities())  

是本教程所必需的。

【讨论】:

  • 顺便说一句,“教程方法”使用了“Linq with SqlType query”。我更喜欢使用“Lambada 表达式与 Linq”。我觉得 SqlType 有点复杂:)
猜你喜欢
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多