Entity framework 使用实体框架(core)在Linq中加入组后左连接
问题:我想使用linq语法实体框架7在所需输出中生成下面的确切sql 问题的目标是生成下面的确切sql! 期望输出 我只能得到完全相同的sql,但有内部连接。我似乎无法得到两个左连接。下面的代码说明了我是如何生成内部连接的,以及生成左连接的失败尝试Entity framework 使用实体框架(core)在Linq中加入组后左连接,entity-framework,linq,Entity Framework,Linq,问题:我想使用linq语法实体框架7在所需输出中生成下面的确切sql 问题的目标是生成下面的确切sql! 期望输出 我只能得到完全相同的sql,但有内部连接。我似乎无法得到两个左连接。下面的代码说明了我是如何生成内部连接的,以及生成左连接的失败尝试 SELECT [a].[AppUserId], [a].[FirstName], [a].[MiddleName], [a].[LastName], [a].[IsInternal], [a].[AspNetUserId], [a].[Picture
SELECT [a].[AppUserId], [a].[FirstName], [a].[MiddleName], [a].[LastName], [a].[IsInternal], [a].[AspNetUserId], [a].[PictureLink], [a].[SignatureLink], [a].[PhoneNumber], [a].[Extension], [a].[FaxNumber], [a].[MobileNumber], [a].[Skype], [a].[SupervisorId], [a].[BackUpId], [a].[HasAutoAssignClaims], [a].[IsActive]
FROM [AppUser] AS [a]
INNER JOIN [AspNetUsers] AS [b] ON [a].[AspNetUserId] = [b].[Id]
INNER JOIN [AspNetUserRoles] AS [c] ON [b].[Id] = [c].[UserId]
INNER JOIN [AspNetRoles] AS [d] ON [a].[RoleId] = [d].[Id]
具有内部联接的代码可以工作,但我需要左联接….:
带有左连接的代码…我缺少了一些概念,但不起作用
不起作用的是,在g2.RoleId等于d.Id的第3组行中,g2不可用。那么,我如何使c.RoleId可用于我的下一个左连接?基本上,当你把一些东西分组后,你显然不能再使用它了
var LeftJoin= (
//INNER JOIN
from a in _dbCtx.AppUser
join b in _dbCtx.Users
on a.AspNetUserId equals b.Id
////LEFT JOIN
join c in _dbCtx.UserRoles
on b.Id equals c.UserId into group2
from g2 in group2.DefaultIfEmpty() //makes it left join
join d in _dbCtx.Roles
on g2.RoleId equals d.Id into group3
from g3 in group3.DefaultIfEmpty()
select new
{
AppUserId = a.AppUserId,
Email = b.Email,
FirstName = a.FirstName,
MiddleName = a.MiddleName,
LastName = a.LastName,
IsInternal = a.IsInternal,
AspNetUserId = a.AspNetUserId,
PictureLink = a.PictureLink,
SignatureLink = a.SignatureLink,
PhoneNumber = a.PhoneNumber,
Extension = a.Extension,
FaxNumber = a.FaxNumber,
MobileNumber = a.MobileNumber,
Skype = a.Skype,
Role = g3.Name != null ? string.Empty :g3.Name ,
SupervisorId = a.SupervisorId,
BackUpId = a.BackUpId,
HasAutoAssignClaims = a.HasAutoAssignClaims,
IsActive = a.IsActive
}).ToList();
这是一种使用非常糟糕的查询生成数据的变通方法。它会生成一系列对数据库的调用,这些调用会产生相同的结果集。然而,这绝对不是这份工作的最佳查询。我仍在等待RC2,我将更新答案
var query = (
//INNER JOIN
from a in _dbCtx.AppUser
join b in _dbCtx.Users
on a.AspNetUserId equals b.Id
from c in _dbCtx.UserRoles
.Where(x => b!=null && x.UserId == b.Id)
.DefaultIfEmpty()
from d in _dbCtx.Roles
.Where(x => a !=null && x.Id == a.RoleId)
.DefaultIfEmpty()
select new
{
AppUserId = a.AppUserId,
Email = b.Email,
FirstName = a.FirstName,
MiddleName = a.MiddleName,
LastName = a.LastName,
IsInternal = a.IsInternal,
AspNetUserId = a.AspNetUserId,
PictureLink = a.PictureLink,
SignatureLink = a.SignatureLink,
PhoneNumber = a.PhoneNumber,
Extension = a.Extension,
FaxNumber = a.FaxNumber,
MobileNumber = a.MobileNumber,
Skype = a.Skype,
Role = d.Name != null ? string.Empty :d.Name ,
SupervisorId = a.SupervisorId,
BackUpId = a.BackUpId,
HasAutoAssignClaims = a.HasAutoAssignClaims,
IsActive = a.IsActive
}).ToList();
如果我理解正确,您的问题是EF并没有生成左连接。若答案是肯定的,那个么解决方案非常简单,比如你们的实体应该有空属性
public class SomeClass
{
public int Id { get; set; }
public int? CategoryId { get; set; }
public Category Category {get;set:}
}
我脑子里有一个选择
_dbCtx.SqlQuery<T>(SqlStringHEre).ToList()
但当我们在评论中谈到IdentityUserRole并没有对role的引用时,这里有一个问题,所以让我们来解决这个问题。
创建类
public class UserToRole : IdentityUserRole<int>
{
public Role Role { get; set; }
}
如果有人来问这个问题,认为它还没有得到回答,那么答案现在就隐藏在问题后面的评论链中。我只是在这里转述主要的评论
问题是EntityFramework7目前是一个新的框架,并且有一些bug。其中一个bug导致OP记录的左连接失败
目前的解决方案是恢复到实体框架6,或者暂时使用存储过程或内联SQL,直到错误被修复。您应该对此进行详细说明:我详细说明了一些概念,即当我在group3中使用g2.RoleId等于d.Id时,g2.RoleId不再可用。总体目标是在任何方法中用左连接复制上面的查询?从语法上看,这似乎是一个正确的语句。它给出了一个例外,即序列没有元素。这是因为在对它们进行分组后,它不再可供调用。您的LeftJoin查询是正确的。在EF6中,它会准确地生成您所期望的内容。在EF7 core中,它根本不起作用,这同样适用于许多其他有效的查询,所以我想说EF7还没有准备好使用。不幸的是,它生成的sql与我上面的查询不等价。其中也不包含在查询中非常重要的角色名称。它也不是最好的sql。记住,我想要的是生成我在上面的问题中提出的确切的sql。从[AspNetUserRoles]中选择[a].[UserId],[a].[RoleId]作为[a]内部联接从[AppUser]中选择DISTINCT*作为[apu]内部联接[AspNetUsers]作为[a]在[apu]上的[a]。[AspNetUserId]=[a0]。[Id]按[a].[Id]顺序排列@hidden你能解释为什么你需要完全相同的查询吗?因为我不敢相信不可能生成简单的左连接…我得到了内部连接等价物为什么做简单的左连接如此困难。如果你需要精确的sql,为什么不把sql放在一个存储过程中,然后从实体框架调用它?@hidden什么意思没有角色的属性_context.Users.Includeu=>u.roles我刚刚在我的项目中尝试过,它可以工作
_dbCtx.SqlQuery<T>(SqlStringHEre).ToList()
var query = _dbCtx.AppUser
.Include(apu=>apu.AspNetUser)
.Include(apu=>apu.AspNetUser.Roles)
.Include(apu=>apu.AspNetUser.Roles.Select(r=>r.Role))
.ToList();
public class UserToRole : IdentityUserRole<int>
{
public Role Role { get; set; }
}
public class YourUser : IdentityUser<int, IdentityUserLogin<int>, UserToRole, IdentityUserClaim<int>>
_db.Users.Select(u=>u.Roles.Select(r=>r.Role.Name))