【问题标题】:1000+ Linq queries or logic in the database...which is worse?数据库中有 1000 多个 Linq 查询或逻辑......哪个更糟?
【发布时间】:2010-06-23 22:15:28
【问题描述】:

我曾在 much more long-winded way a few days ago 中提出过这个问题,考虑到篇幅,我没有得到答案这一事实并不令人惊讶,所以我想我会更深入地了解这一点。

我必须根据分配给特定客户的用户来决定向用户显示什么。域对象看起来像这个大大简化的示例:

public class Customer
{
    public string Name { get; set; }
    public IEnumerable<Users> AssignedUsers { get; set; }
}

在现实世界中,我还将评估他们是否有权限(使用安全标志上的按位比较)来查看该特定客户,即使他们没有直接分配给它。

我在这里尝试坚持domain-driven design (DDD) 原则。此外,我使用 LINQ to SQL 进行数据访问。在我的服务层中,我为请求客户列表的用户提供服务,现在大约有 1000 个项目,并且每月增长约 2%。

如果我严格要求在服务层中保留逻辑,我将需要使用 Linq 执行 .Where 评估 AssignedUsers 列表是否包含请求列表的用户。这将导致系统枚举时对每个Customer 进行级联查询。我没有做任何测试,但这似乎效率低下。

如果我对 no-logic-in-the-data 进行忽悠,那么我可以简单地使用 GetCustomersByUser() 方法来执行 EXISTS 类型的 SQL 查询并同时评估安全性。这肯定会更快,但现在我说的是潜入数据库的逻辑,这可能会在以后产生问题。

我敢肯定,这是人们在推出 Linq 时会遇到的一个常见问题......关于哪种方式更好的建议? Linq 的多个查询对性能的影响是否比我的数据库中的逻辑更好?

【问题讨论】:

  • 如果您主要尝试检索分配给用户的客户,您是否应该不修改您的对象,并拥有一个包含已分配客户列表的用户?
  • 实际上伴随着用户分配的数据——例如他们收到的佣金。结果,无论您以哪种方式看待它,多对多关系都将需要单独的分配对象。我们也是批发的,所以用户是我们真正的客户。
  • 我正在考虑更多关于该评论...实际上可能有一种方法可以翻转它并使 Assignment 对象及其数据专注于客户而不是用户...

标签: c# performance linq-to-sql domain-driven-design


【解决方案1】:

哪个更糟? 取决于你问谁。

如果您问 DDD 超纯粹主义者,他们可能会说数据库中的逻辑更糟糕。

如果您问其他任何人,恕我直言,尤其是您的最终用户、务实的开发人员以及为硬件和软件开发付费的人,他们可能会说大幅降低性能会更糟。

DDD 有很多值得称赞的地方,许多其他设计方法也是如此,但是如果你教条地遵循它们以牺牲“纯粹”设计为代价,它们全部都会失败现实世界的考虑因素,例如性能。

如果您确实必须对数据执行此类查询,那么几乎可以肯定数据库在执行任务方面更好。

或者,您在这里“错过了一个技巧”。你的设计,不管是 DDD,真的不对吗?

总体而言 - 适当地使用您的工具。尽一切努力在您的服务层中保持逻辑清晰分离,但当该逻辑正在执行数据库设计的大量工作时则不是。

【讨论】:

  • 关于设计的有趣问题...我想知道 DDD 是否真的是这里最好的模式,因为这本质上是一个数据库应用程序,其业务逻辑主要是工作流和状态管理,其中很大一部分进行货币计算。因此,“域”本质上是关系型的(再说一遍,我猜什么域不是),我可能会将关系数据库原则硬塞到我的域对象中。
  • @downvoter - 为什么投反对票?我很想知道你不同意什么,所以请发表评论。
  • 因为这不是有用的答案。
  • 感谢 Arnis L。这不是一个特别有见地的评论,也不是很有帮助,但感谢您的尝试。我更希望邀请反对者参与描述他们不同意的内容,因为在我看来,讨论和批评是学习的一个相当关键的部分。回想起来,您可能不值得留下该评论,因为它并没有真正添加任何内容。除了我屏幕上的 34 个字符之外,就是这样。
【解决方案2】:

LINQ 是一种抽象,它将一堆功能包装到一个漂亮的小包中,顶部有一颗大心脏。

使用任何抽象,您都会获得开销,主要是因为事情没有您或我想要的那么高效。 MS 在提高 LINQ 的效率方面做得很好。

逻辑应该在需要的地方。Pure 很好,但是如果您要提供服务或产品,则必须牢记以下几点(这些没有特别的顺序):

  1. 维护。在它发布后,您是否能够轻松完成一些工作,而无需拆散整个事情。
  2. 可扩展性。
  3. 性能
  4. 可用性。

数字 3 是使用网络时最重要的方面之一。你会在 SQL Server 上做三角函数吗?不会。您会根据输入参数过滤结果吗?是的。

SQL Server 旨在处理大量查询、过滤、排序和数据挖掘。它会因此而茁壮成长,所以让它去做吧。

这不是逻辑蠕变,而是将功能放在应有的位置。

【讨论】:

  • +1 表示“这不是逻辑蠕变,而是将功能放在应有的位置。”
【解决方案3】:

如果 AssignedUser 被正确映射(即关联是由 Linq2SQL 设计器生成的,或者您有带有 AssosiationAttribute 的标记属性(或来自http://msdn.microsoft.com/en-us/library/system.data.linq.mapping(v=VS.90).aspx 命名空间的其他属性,我现在不确定),Linq2Sql 会将 linq 查询转换为 SQL 命令,并且不会为每个客户遍历 AssingedUser。

你也可以使用'reversed'查询

from c in Customer
join u in Users on c.CustomerId equals u.AssignedToCustomerId // or other condition links user to customer
where <you condition here>
select c

【讨论】:

    【解决方案4】:

    如果我严格要求在服务层中保留逻辑,我将需要使用 Linq 执行 .Where 来评估 AssignedUsers 列表是否包含请求列表的用户。当系统枚举时,这将导致每个客户的级联查询。我没有做任何测试,但这似乎效率低下。

    应该不需要枚举本地客户集合。

    LinqToSql 的主要目的,是让你在服务层声明逻辑,并在数据层执行该逻辑。

    int userId = CurrentUser.UserId;
    
    IEnumerable<Customer> customerQuery =
      from c in dataContext.Customers
      where c.assignedUsers.Any(au => au.UserId = userId)
      select c;
    
    List<Customer> result = customerQuery.ToList();
    

    【讨论】:

      【解决方案5】:

      我认为最好将您的模型描述为 Customer 类和 User 类之间的多对多关系。每个用户引用一个相关客户列表,每个客户引用一个相关用户列表。从数据库的角度来看,这是使用连接表表示的(根据 Microsoft 的 LINQ to SQL 术语,他们称之为“连接表”)。

      多对多关系是 LINQ to SQL 不支持开箱即用的一项功能,如果您尝试生成 DBML,您可能会注意到这一点。

      一些博客已经发布了解决方法,其中一个来自 MSDN(很遗憾,没有任何具体示例)。有一个博客(两部分的帖子)非常符合 MSDN 的建议:

      http://blogs.msdn.com/b/mitsu/archive/2007/06/21/how-to-implement-a-many-to-many-relationship-using-linq-to-sql.aspx

      http://blogs.msdn.com/b/mitsu/archive/2008/03/19/how-to-implement-a-many-to-many-relationship-using-linq-to-sql-part-ii-add-remove-support.aspx

      【讨论】:

        【解决方案6】:

        我个人会使用存储过程。这是工作的正确工具。 不使用它可能是一个不错的设计选择,但在我看来,设计范例可以指导你,而不是限制你。 另外,老板只关心性能:-)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-02
          • 1970-01-01
          • 1970-01-01
          • 2011-03-02
          • 1970-01-01
          • 2016-03-19
          相关资源
          最近更新 更多