Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Entity Framework Core 5.0如何将LINQ转换为多对多连接以使用ASP.NET成员身份的交集表_C#_Sql Server_Linq_Entity Framework Core_Entity Framework 6 - Fatal编程技术网

C# Entity Framework Core 5.0如何将LINQ转换为多对多连接以使用ASP.NET成员身份的交集表

C# Entity Framework Core 5.0如何将LINQ转换为多对多连接以使用ASP.NET成员身份的交集表,c#,sql-server,linq,entity-framework-core,entity-framework-6,C#,Sql Server,Linq,Entity Framework Core,Entity Framework 6,问题: 如何将LINQ查询转换为对内部联接两个表并具有谓词的子选择执行左外部联接 上下文: 我正在使用EFCore工具反向工程功能从entityframework6(EF6)升级到entityframeworkcore 5(EFCore)。我有一个查询,它使用LINQ查询系统上AspNet\u用户和AspNet\u角色表之间的多对多关系。查询通过AspNet\u UsersInRoles交集表抽象出连接。因此,在EF6中,我有以下LINQ: (from r in this.DbContext.a

问题: 如何将LINQ查询转换为对内部联接两个表并具有谓词的子选择执行左外部联接

上下文: 我正在使用
EFCore工具
反向工程功能从
entityframework6(EF6)
升级到
entityframeworkcore 5(EFCore)
。我有一个查询,它使用LINQ查询系统上
AspNet\u用户
AspNet\u角色
表之间的多对多关系。查询通过
AspNet\u UsersInRoles
交集表抽象出连接。因此,在EF6中,我有以下LINQ:

(from r in this.DbContext.aspnet_Users
where r.UserId == dpass.UserId
select r.aspnet_Roles.Select(x => x.RoleName)
).FirstOrDefault();
生成以下SQL查询(使用SQL Server探查器检索):

这将生成以下SQL查询(使用EFCore的新
.ToQueryString()
方法检索):

aspnet\u角色

[Index(nameof(RoleId), Name = "aspnet_UsersInRoles_index")]
public partial class aspnet_UsersInRoles
{
    [Key]
    public Guid UserId { get; set; }
    [Key]
    public Guid RoleId { get; set; }

    [ForeignKey(nameof(RoleId))]
    [InverseProperty(nameof(aspnet_Roles.aspnet_UsersInRoles))]
    public virtual aspnet_Roles Role { get; set; }
    [ForeignKey(nameof(UserId))]
    [InverseProperty(nameof(aspnet_Users.aspnet_UsersInRoles))]
    public virtual aspnet_Users User { get; set; }
}
public partial class aspnet_Roles
{
    public aspnet_Roles()
    {
        aspnet_UsersInRoles = new HashSet<aspnet_UsersInRoles>();
    }

    public Guid ApplicationId { get; set; }
    [Key]
    public Guid RoleId { get; set; }
    [Required]
    [StringLength(256)]
    public string RoleName { get; set; }
    [Required]
    [StringLength(256)]
    public string LoweredRoleName { get; set; }
    [StringLength(256)]
    public string Description { get; set; }

    [ForeignKey(nameof(ApplicationId))]
    [InverseProperty(nameof(aspnet_Applications.aspnet_Roles))]
    public virtual aspnet_Applications Application { get; set; }
    [InverseProperty("Role")]
    public virtual ICollection<aspnet_UsersInRoles> aspnet_UsersInRoles { get; set; }
}
[Index(nameof(ApplicationId), nameof(LastActivityDate), Name = "aspnet_Users_Index2")]
public partial class aspnet_Users
{
    public aspnet_Users()
    {
        Users = new HashSet<Users>();
        aspnet_PersonalizationPerUser = new HashSet<aspnet_PersonalizationPerUser>();
        aspnet_UsersInRoles = new HashSet<aspnet_UsersInRoles>();
    }

    public Guid ApplicationId { get; set; }
    [Key]
    public Guid UserId { get; set; }
    [Required]
    [StringLength(256)]
    public string UserName { get; set; }
    [Required]
    [StringLength(256)]
    public string LoweredUserName { get; set; }
    [StringLength(16)]
    public string MobileAlias { get; set; }
    public bool IsAnonymous { get; set; }
    [Column(TypeName = "datetime")]
    public DateTime LastActivityDate { get; set; }

    [ForeignKey(nameof(ApplicationId))]
    [InverseProperty(nameof(aspnet_Applications.aspnet_Users))]
    public virtual aspnet_Applications Application { get; set; }
    [InverseProperty("User")]
    public virtual aspnet_Membership aspnet_Membership { get; set; }
    [InverseProperty("User")]
    public virtual aspnet_Profile aspnet_Profile { get; set; }
    [InverseProperty("aspUser")]
    public virtual ICollection<Users> Users { get; set; }
    [InverseProperty("User")]
    public virtual ICollection<aspnet_PersonalizationPerUser> aspnet_PersonalizationPerUser { get; set; }
    [InverseProperty("User")]
    public virtual ICollection<aspnet_UsersInRoles> aspnet_UsersInRoles { get; set; }
}
公共部分类aspnet\u角色
{
公共aspnet_角色()
{
aspnet_UsersInRoles=new HashSet();
}
公共Guid应用程序ID{get;set;}
[关键]
公共Guid RoleId{get;set;}
[必需]
[StringLength(256)]
公共字符串RoleName{get;set;}
[必需]
[StringLength(256)]
公共字符串LowereRoleName{get;set;}
[StringLength(256)]
公共字符串说明{get;set;}
[ForeignKey(name of(ApplicationId))]
[InverseProperty(名称(aspnet_Applications.aspnet_Roles))]
公共虚拟aspnet_应用程序应用程序{get;set;}
[反向属性(“角色”)]
公共虚拟ICollection aspnet_UsersInRoles{get;set;}
}
aspnet\u用户

[Index(nameof(RoleId), Name = "aspnet_UsersInRoles_index")]
public partial class aspnet_UsersInRoles
{
    [Key]
    public Guid UserId { get; set; }
    [Key]
    public Guid RoleId { get; set; }

    [ForeignKey(nameof(RoleId))]
    [InverseProperty(nameof(aspnet_Roles.aspnet_UsersInRoles))]
    public virtual aspnet_Roles Role { get; set; }
    [ForeignKey(nameof(UserId))]
    [InverseProperty(nameof(aspnet_Users.aspnet_UsersInRoles))]
    public virtual aspnet_Users User { get; set; }
}
public partial class aspnet_Roles
{
    public aspnet_Roles()
    {
        aspnet_UsersInRoles = new HashSet<aspnet_UsersInRoles>();
    }

    public Guid ApplicationId { get; set; }
    [Key]
    public Guid RoleId { get; set; }
    [Required]
    [StringLength(256)]
    public string RoleName { get; set; }
    [Required]
    [StringLength(256)]
    public string LoweredRoleName { get; set; }
    [StringLength(256)]
    public string Description { get; set; }

    [ForeignKey(nameof(ApplicationId))]
    [InverseProperty(nameof(aspnet_Applications.aspnet_Roles))]
    public virtual aspnet_Applications Application { get; set; }
    [InverseProperty("Role")]
    public virtual ICollection<aspnet_UsersInRoles> aspnet_UsersInRoles { get; set; }
}
[Index(nameof(ApplicationId), nameof(LastActivityDate), Name = "aspnet_Users_Index2")]
public partial class aspnet_Users
{
    public aspnet_Users()
    {
        Users = new HashSet<Users>();
        aspnet_PersonalizationPerUser = new HashSet<aspnet_PersonalizationPerUser>();
        aspnet_UsersInRoles = new HashSet<aspnet_UsersInRoles>();
    }

    public Guid ApplicationId { get; set; }
    [Key]
    public Guid UserId { get; set; }
    [Required]
    [StringLength(256)]
    public string UserName { get; set; }
    [Required]
    [StringLength(256)]
    public string LoweredUserName { get; set; }
    [StringLength(16)]
    public string MobileAlias { get; set; }
    public bool IsAnonymous { get; set; }
    [Column(TypeName = "datetime")]
    public DateTime LastActivityDate { get; set; }

    [ForeignKey(nameof(ApplicationId))]
    [InverseProperty(nameof(aspnet_Applications.aspnet_Users))]
    public virtual aspnet_Applications Application { get; set; }
    [InverseProperty("User")]
    public virtual aspnet_Membership aspnet_Membership { get; set; }
    [InverseProperty("User")]
    public virtual aspnet_Profile aspnet_Profile { get; set; }
    [InverseProperty("aspUser")]
    public virtual ICollection<Users> Users { get; set; }
    [InverseProperty("User")]
    public virtual ICollection<aspnet_PersonalizationPerUser> aspnet_PersonalizationPerUser { get; set; }
    [InverseProperty("User")]
    public virtual ICollection<aspnet_UsersInRoles> aspnet_UsersInRoles { get; set; }
}
[索引(nameof(ApplicationId)、nameof(LastActivityDate)、Name=“aspnet\u Users\u Index2”)]
公共部分类aspnet\u用户
{
公共aspnet_用户()
{
Users=newhashset();
aspnet_PersonalizationPerUser=new HashSet();
aspnet_UsersInRoles=new HashSet();
}
公共Guid应用程序ID{get;set;}
[关键]
公共Guid用户标识{get;set;}
[必需]
[StringLength(256)]
公共字符串用户名{get;set;}
[必需]
[StringLength(256)]
公共字符串LoweredUserName{get;set;}
[第16段]
公共字符串MobileAlias{get;set;}
公共布尔是非对称的{get;set;}
[列(TypeName=“datetime”)]
公共日期时间LastActivityDate{get;set;}
[ForeignKey(name of(ApplicationId))]
[InverseProperty(名称(aspnet_Applications.aspnet_Users))]
公共虚拟aspnet_应用程序应用程序{get;set;}
[反向属性(“用户”)]
公共虚拟aspnet_成员身份aspnet_成员身份{get;set;}
[反向属性(“用户”)]
公共虚拟aspnet_配置文件aspnet_配置文件{get;set;}
[反向属性(“aspUser”)]
公共虚拟ICollection用户{get;set;}
[反向属性(“用户”)]
公共虚拟ICollection aspnet_PersonalizationPerUser{get;set;}
[反向属性(“用户”)]
公共虚拟ICollection aspnet_UsersInRoles{get;set;}
}

如果我是你,我会这样写这个查询:

var result = context.UserRoles
                    .Where(x => x.UserId == ID_TO_SEARCH)
                    .Join(
                        context.Roles,
                        ur => ur.RoleId,
                        r => r.Id,
                        (ur, role) => new
                        {
                            ur,
                            role
                        }
                    )
                    .Select(x => x.role.Name)
                    .FirstOrDefault();
这就产生了一个查询,对我来说,这个查询非常好,也更加优雅:

SELECT TOP(1) [a0].[Name]
FROM [AspNetUserRoles] AS [a]
INNER JOIN [AspNetRoles] AS [a0] ON [a].[RoleId] = [a0].[Id]
WHERE [a].[UserId] = N''
更新:

如果我正确理解评论中的问题,则此查询将选择一个角色名称,如LEFT JOIN:

var rolesQuery = context.UserRoles
                         .Join(
                            context.Roles,
                            ur => ur.RoleId,
                            r => r.Id,
                            (ur, r) => new
                            {
                                ur,
                                r
                            }
                        );
                    
    var result = context.Users
                        .Where(x => x.Id == "")
                        .Select(u => new
                        {
                           Name = u.UserName,
                           Role = rolesQuery
                               .Where(sub=> sub.ur.UserId == u.Id)
                               .Select(sub=> sub.r.Name)
                               .FirstOrDefault()
                        })
                        .FirstOrDefault();
这将导致下一个SQL:

      SELECT TOP(1) [a1].[UserName] AS [Name], (
          SELECT TOP(1) [a0].[Name]
          FROM [AspNetUserRoles] AS [a]
          INNER JOIN [AspNetRoles] AS [a0] ON [a].[RoleId] = [a0].[Id]
          WHERE [a].[UserId] = [a1].[Id]) AS [Role]
      FROM [AspNetUsers] AS [a1]
      WHERE [a1].[Id] = N''
正如您所看到的,并没有左连接,但sub-select将以与左连接类似的方式返回数据。不幸的是,基于lambda的查询不支持完全左连接,编写真正左连接的唯一选项可以使用类似SQL的iQuery来丰富


我在EF core 5库中看到一个名为
LeftJoin()
的方法,但它抛出NotImplementedException。我认为这是稍后将发布的内容

如果您只需要特定用户的角色名称,查询应该简化:

var查询=
从this.DbContext.aspnet_用户中的r
其中r.UserId==dpass.UserId
来自r.aspnet_角色中的ro
选择ro.RoleName;

首先,两个LINQ查询并不等价-原始查询从主表
aspnet\u Users
开始,而转换后的查询从联接表
aspnet\u UsersInRoles
开始。这立刻产生了不同。第二,为什么要重写原始查询?EFC 5支持多对多隐式联接表,其方式与EF6完全相同,因此只需放置相同的导航属性,删除显式联接实体(但由于它使用非常规名称而对其进行配置),就可以只使用现有查询。@IvanStoev我已提供了对我的问题的更新。我想如果EFCore支持多对多关系,那么我就不会出现这些错误。所以,我试着重新编写LINQ。你知道我如何解决这个问题吗?@IvanStoev:除非EFC5添加了它(我没有听说过),否则EF Core不支持隐式多对多。您需要明确地执行此操作,即,假装这是与您自己创建的交叉表的两个一对多关系:“当您定义多对多关系时,像这样的链接表[…]EF6.x为您创建了此表,但EF Core采用更精简的方法,它不这样做–您需要这样做。”@Flater它是中的顶级功能。文档。我需要
UserId
RoleName
。但是,我得到的错误与我在今天早上的问题更新中提供的错误相同。关于如何修复它有什么想法吗?用户ID是已知的,您不必选择它。异常显示您的导航属性
aspnet\u角色有问题。很难说发生了什么。@dantety89感谢您提供此查询的lambda版本。作为学习练习,我如何将
UserId
列添加到输出中?正如@SvyatoslavDanyliv提到的,我不需要