C# LINQ联合vs SQL联合
我在C# LINQ联合vs SQL联合,c#,sql-server,entity-framework,linq,C#,Sql Server,Entity Framework,Linq,我在用户和用户项目之间建立关系UserProjects.UserId对Users.UserId的引用 我想查找位于UserProjects中且UserProject具有UsreProjects.projectd==4的用户。然后将其余用户合并到此表 事实上,我想更改User的一些属性,UserProject=4 在MSSQL中,为了测试我有下面的查询 Select U.UserId from Users U Join UserProjects UP On U.UserId = up.UserI
用户
和用户项目
之间建立关系UserProjects.UserId
对Users.UserId的引用
我想查找位于UserProjects
中且UserProject
具有UsreProjects.projectd==4的用户。然后将其余用户合并到此表
事实上,我想更改User的一些属性,UserProject=4
在MSSQL中,为了测试我有下面的查询
Select U.UserId
from Users U
Join UserProjects UP
On U.UserId = up.UserId
Where up.ProjectId = 4
Union
Select U.UserId From Users U
我不会改变任何属性。无论如何,结果是它向我展示了它应该展示的整个用户
但是现在使用相同的查询来更改属性会导致比我拥有更多的用户
var usrs = ((from users in context.Users
join userProj in context.UserProjects
on users.UserId equals userProj.UserId
where userProj.ProjectId == projectId
select new ProjectUsersDTO
{
UserName = users.Name,
Rate = users.RatePerHour,
UserId = users.UserId,
alreadyInProject = true
})
.Union(from users in context.Users
select new ProjectUsersDTO
{
UserName = users.Name,
Rate = users.RatePerHour,
UserId = users.UserId,
alreadyInProject = false
}))
.ToList();
return usrs;
当工会不允许复制时,情况如何
再见,谢谢 解释了SQL联合
(执行隐式DISTINCT
)和LINQ联合
(需要显式DISTINCT()
)之间的行为差异
因此,对于您的特定情况,只需对查询应用Distinct()
。唯一性/无重复性基于完整的记录/ProjectUsersDTO实例
项目4中的用户(或变量projectd的任何值)将在结果中出现两次,一次是alreadyInProject=true,另一次是alreadyInProject=false。
第一个选择仅选择项目中的用户,第二个选择选择所有用户(包括项目中的用户)。它们被视为不同的记录,因为alreadyInProject的值不同,所以两个版本都将出现在输出中
我不确定您想要什么,但我假设您想要一个包含所有用户的列表,并指示他们是否在具有给定projectId的项目中。
你可以使用这个代码
var usrs = (from users in context.Users
join userProj in context.UserProjects
on users.UserId equals userProj.UserId
select new ProjectUsersDTO
{
UserName = users.Name,
Rate = users.RatePerHour,
UserId = users.UserId,
alreadyInProject = (userProj.ProjectId == projectId)
})
.ToList();
return usrs;
LINQ联合vs SQL联合
它们是等价的
但是现在使用相同的查询来更改属性会导致比我拥有更多的用户
var usrs = ((from users in context.Users
join userProj in context.UserProjects
on users.UserId equals userProj.UserId
where userProj.ProjectId == projectId
select new ProjectUsersDTO
{
UserName = users.Name,
Rate = users.RatePerHour,
UserId = users.UserId,
alreadyInProject = true
})
.Union(from users in context.Users
select new ProjectUsersDTO
{
UserName = users.Name,
Rate = users.RatePerHour,
UserId = users.UserId,
alreadyInProject = false
}))
.ToList();
return usrs;
这与查询不一样。在第一个(SQL)查询中,您只选择(包括)一个字段(UserId
),而在第二个(LINQ)查询中,您包括两个字段,其中一个字段肯定是不同的。由于Union
使用所有包含的字段作为判断项目是否唯一的标准,因此第二次查询返回更多项目是正常的
话虽如此,让我们看看如何解决具体问题。看起来您根本不需要Union
。通常您应该有一个导航属性,因此像这样的简单查询应该可以完成这项工作(假设导航属性称为项目
):
你提供的链接根本无法解释差异。它讨论的是内存中的linq,而不是ef或l2s。只要对象具有可比性和相等性,linq并集就会产生唯一的对象。您正在讨论的对象是ProjectUsersDTO。我认为您需要在这个对象上实现一个IEquatable接口,以便联盟按照您的意愿工作。此外,由于“alreadyInProject”[sic]属性不相同,因此您的值集略有不同。如果IEquatable实现忽略此属性,则这无关紧要。您正在使用IEnumerable.Union,因为您在该Union之前投影到DTO。如果希望数据库执行distinct,则需要将对DTO的投影推迟到union之后。因此,在两个查询中都投影到一个匿名类型,然后是union,然后添加一个AsEnumerable()调用,然后投影到DTO,然后执行ToList()。@Maarten我正要添加它。