EF Core DB First中Scaffold-DBContext未生成UserGroups实体类问题
EF Core多对多关系未生成中间表实体类的问题及查询实现
问题背景
现有User、Groups两张表,通过中间表UserGroups构成多对多关系(一个用户可属于多个组,一个组可包含多个用户)。使用Scaffold-DBContext生成模型时,未生成UserGroups实体类,这是否符合预期?
以下是User表的上下文代码片段:
modelBuilder.Entity<User>(entity => { entity.ToTable("User"); entity.HasIndex(e => e.AccessLevelId, "IX_User_AccessLevelId"); entity.Property(e => e.Azid).HasColumnName("AZID"); entity.Property(e => e.Department).HasDefaultValueSql("(N'')"); entity.HasOne(d => d.AccessLevel).WithMany(p => p.Users).HasForeignKey(d => d.AccessLevelId); entity.HasMany(d => d.Groups).WithMany(p => p.Users) .UsingEntity<Dictionary<string, object>>( "UserGroup", r => r.HasOne<Group>().WithMany().HasForeignKey("GroupId"), l => l.HasOne<User>().WithMany().HasForeignKey("UserId"), j => { j.HasKey("UserId", "GroupId"); j.ToTable("UserGroups"); j.HasIndex(new[] { "GroupId" }, "IX_UserGroups_GroupId"); }); });
可见EF已识别该关系,但未创建UserGroup模型类。若此为预期行为,如何实现检查用户是否属于Admin组的需求?原查询代码如下:
return await (from u in _context.Users join ug in _context.UserGroup on u.UserId equals ug.UserId join g in _context.Groups on ug.GroupId equals g.GroupId where u.Azid == userAZID && g.Name.ToLower() == "admin" select u.UserId ).FirstOrDefaultAsync();
解答
1. 未生成UserGroups实体类是否符合预期?
这是完全符合预期的行为。EF Core在处理纯关联型中间表(仅包含两个外键作为复合主键,无额外业务字段)时,会自动将其识别为多对多关系的隐式关联表,无需生成对应的实体类。从上下文配置代码也能看到,EF Core已经通过UsingEntity<Dictionary<string, object>>完成了多对多关系的映射,这种设计可以简化代码,避免冗余的实体类。
2. 实现检查用户是否属于Admin组的方案
由于EF Core已经通过导航属性维护了User和Groups的多对多关系,你不需要手动关联中间表,直接使用导航属性即可完成查询,代码更简洁高效:
方案一:LINQ查询语法
return await (from u in _context.Users where u.Azid == userAZID && u.Groups.Any(g => g.Name.ToLower() == "admin") select u.UserId).FirstOrDefaultAsync();
方案二:LINQ方法语法
return await _context.Users .Where(u => u.Azid == userAZID && u.Groups.Any(g => g.Name.ToLower() == "admin")) .Select(u => u.UserId) .FirstOrDefaultAsync();
如果一定要模拟原查询的关联逻辑,也可以通过EF Core映射的隐式中间表进行查询,但这种写法不够直观,不推荐:
return await _context.Users .Join( _context.Set<Dictionary<string, object>>("UserGroups"), u => u.UserId, ug => ug["UserId"], (u, ug) => new { User = u, UserGroup = ug } ) .Join( _context.Groups, x => x.UserGroup["GroupId"], g => g.GroupId, (x, g) => new { x.User, Group = g } ) .Where(x => x.User.Azid == userAZID && x.Group.Name.ToLower() == "admin") .Select(x => x.User.UserId) .FirstOrDefaultAsync();
内容的提问来源于stack exchange,提问作者TechTurtle
相关产品推荐
相关产品推荐

