如何使用实体框架在c#中对多对多关系运行linq查询

本文关键字:关系 linq 查询 运行 实体 何使用 框架 | 更新日期: 2023-09-27 18:01:08

我在查询Linq-to实体中的多对多关系时遇到问题。我基本上是在尝试使用Linq:复制这个查询

SELECT  
    Users.UserName, Roles.RoleName, Users.IsActive 
FROM 
    Users
LEFT JOIN 
    UserRoles ON Users.UserID = UserRoles.UserID
LEFT JOIN 
    Roles ON UserRoles.RoleID = Roles.RoleID

我在Linqpad中尝试了这个查询,它运行得非常好

Users.Join(UserRoles, u=>u.UserId, r=>r.UserId, (u,r) => new { u, r})
      .Join(Roles, ur=>ur.r.RoleId, q=>q.RoleId, (ur,q)=>new {ur, q})
      .Select(m=> new {m.ur.u.UserName, m.ur.u.IsActive, m.q.RoleName})

但是当我在C#应用程序中尝试相同的查询时,它会抛出一个错误

错误

"Context"不包含"UserRoles"的定义,也找不到接受"Context"类型的第一个参数的扩展方法"UserRole"(是否缺少using指令或程序集引用?(

我的问题是如何在C#中创建LINQ查询来检索分配给RolesUsers

我的DbContext包含

public class Context : DbContext
{
    public Context()
        : base("Name=xyz")
    {
        if (!Database.Exists("xyz"))
            Database.SetInitializer(new Initializer());
    }
    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new UserMap());
        base.OnModelCreating(modelBuilder);
    }
}
public class UserMap : EntityTypeConfiguration<User>
{
    public UserMap()
    {
        HasMany(r => r.Roles).WithMany(u=>u.Users)
            .Map(m =>
            {
                m.ToTable("UserRoles");
                m.MapLeftKey("UserId");
                m.MapRightKey("RoleId");
            });
    }
}
public class User
{
    public User()
    {
        this.Roles = new HashSet<Role>();
    }
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string PasswordHash { get; set; }
    public DateTime? LastLoggedOn { get; set; }
    public DateTime? PasswordChangedOn { get; set; }
    public int IsActive { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}
public class Role
{
    public Role()
    {
        this.Users = new HashSet<User>();
    }
    public int RoleId { get; set; }
    public string RoleName { get; set; }
    public string Description { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

如何使用实体框架在c#中对多对多关系运行linq查询

编辑:查看问题中的代码:没有定义UserRoles。您需要根据EF进行重构,了解多-多关系:
var res = db.Users.SelectMany(u => 
                  u.Roles.Select(r =>
                      new {
                        u.UserName,
                        r.RoleName,
                        u.IsActive
                      }
                  )
          );

EF了解(因为您已经定义了它(如何进行联接:代表关系的Roles集合将只过滤属于您开始使用的用户的角色。


原始答案

编写查询的方法的定义是什么类型的?

LINQpad(IIRC(运行一切,就好像它是DbContext派生类型的方法一样。因此,DbSet<T>属性映射表可以在没有限定的情况下使用(在您的案例中为UserRoles(。如果不是上下文类型的成员,则需要使用上下文的实例来限定实体集:

using (var db = new MyContext()) {
  var data = db.Users.Join(db.UserRoles, u=>u.UserId, r=>r.UserId, (u,r) => new { u, r})
               .Join(db.Roles, ur=>ur.r.RoleId, q=>q.RoleId, (ur,q)=>new {ur, q})
               .Select(m=> new {m.ur.u.UserName, m.ur.u.IsActive, m.q.RoleName})
}