我曾在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的多个查询的性能是否比我的数据库中的逻辑更好?
答案 0 :(得分:5)
哪个更糟? 取决于你问谁。
如果你问DDD超纯粹主义者,他们会说数据库中的逻辑更糟糕。
如果你问其他任何人,恕我直言,特别是你的最终用户,实用的开发人员以及为硬件和软件开发付费的人,他们可能会说性能受到的影响更大。
DDD有很多值得赞扬的地方,就像许多其他设计方法一样,但是如果你教条地追随它们以达到“纯粹”设计的代价,那么它们所有都会失败现实世界的考虑,例如表现。
如果您真的必须对数据执行此类查询,那么数据库几乎肯定远更好地执行任务。
或者,你在这里“错过了一招”。你的设计,不管DDD,实际上不对吗?
总体而言 - 适当使用您的工具。无论如何都要努力在您的服务层中保持逻辑清晰,而不是在逻辑正在进行数据库设计的大量工作时。
答案 1 :(得分:3)
LINQ是一个抽象概念,它将一堆功能包装在一个很棒的小包装中,并且有一颗大心脏。
任何抽象,你都会得到开销,主要是因为事情不如你或我想要的那么高效。 MS在使LINQ非常有效方面做得很好。
逻辑应该是需要的地方。纯粹是好的,但是如果你提供服务或产品,你必须考虑以下因素(这些没有特别的顺序):
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的建议:
答案 5 :(得分:0)
我个人会使用存储过程。这是适合工作的工具。 不使用它可能是一个不错的设计选择,但在我看来,设计范例可以指导你,而不是限制你。 另外,老板只关心表现: - )