1000+ Linq查询或数据库中的逻辑......哪个更糟?

时间:2010-06-23 22:15:28

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

我曾在much more long-winded way a few days ago中提出这个问题,考虑到长度,我没有得到答案的事实并不令人惊讶,所以我认为我会更多地提到这一点。

我必须根据对特定客户的分配来决定显示用户的内容。域对象看起来像这个极其简化的例子:

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

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

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

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

如果我捏造数据中的无逻辑,那么我可以简单地使用GetCustomersByUser()方法执行EXISTS类型的SQL查询并同时评估安全性。这肯定会更快,但现在我说的是逻辑爬进数据库,这可能会在以后产生问题。

我确信这是人们在推出Linq时提出的一个常见问题...有哪些建议更好? Linq的多个查询的性能是否比我的数据库中的逻辑更好?

6 个答案:

答案 0 :(得分:5)

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

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

如果你问其他任何人,恕我直言,特别是你的最终用户,实用的开发人员以及为硬件和软件开发付费的人,他们可能会说性能受到的影响更大。

DDD有很多值得赞扬的地方,就像许多其他设计方法一样,但是如果你教条地追随它们以达到“纯粹”设计的代价,那么它们所有都会失败现实世界的考虑,例如表现。

如果您真的必须对数据执行此类查询,那么数据库几乎肯定更好地执行任务。

或者,你在这里“错过了一招”。你的设计,不管DDD,实际上不对吗?

总体而言 - 适当使用您的工具。无论如何都要努力在您的服务层中保持逻辑清晰,而不是在逻辑正在进行数据库设计的大量工作时。

答案 1 :(得分:3)

LINQ是一个抽象概念,它将一堆功能包装在一个很棒的小包装中,并且有一颗大心脏。

任何抽象,你都会得到开销,主要是因为事情不如你或我想要的那么高效。 MS在使LINQ非常有效方面做得很好。

逻辑应该是需要的地方。纯粹是好的,但是如果你提供服务或产品,你必须考虑以下因素(这些没有特别的顺序):

  1. 维护。在发布之后你是否能够轻松地完成一些工作而不会将整个事情分开。
  2. 可扩展性。
  3. 性能
  4. 可用性。
  5. 3号是使用网络时最重要的方面之一。你会在SQL Server上做三角学吗?不会。您会根据输入参数过滤结果吗?是。

    SQL Server用于处理大量查询,过滤,排序和数据挖掘。它茁壮成长,所以让它做到。

    这不是一个逻辑蠕变,而是将功能放在它所属的位置。

答案 2 :(得分:1)

如果AssignedUser被正确映射(即,Linq2SQL设计者生成了assosiation,或者你有了AssosiationAttribute的标记属性(或http://msdn.microsoft.com/en-us/library/system.data.linq.mapping(v=VS.90).aspx命名空间中的其他一些,我现在不确定),Linq2Sql会将linq查询转换为SQL命令,不会为每个客户迭代AssingedUser。

您也可以使用“反向”查询,如

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

答案 3 :(得分:1)

  

如果我严格要求在我的服务层中保留逻辑,我将需要使用Linq来执行。这会评估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();

答案 4 :(得分:1)

我认为您的模型最好描述为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

答案 5 :(得分:0)

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