簡體   English   中英

如何使用實體框架在C#中的多對多關系上運行linq查詢

[英]How to run linq query on many-to-many relationship in c# with entity framework

我在查詢Linq To Entities中的多對多關系時遇到問題。 我基本上是想使用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#應用程序中嘗試相同的查詢時,它將引發錯誤

錯誤

“上下文”不包含“ UserRoles”的定義,找不到可以接受類型為“ Context”的第一個參數的擴展方法“ UserRoles”(是否缺少using指令或程序集引用?)

我的問題是如何在C#創建LINQ查詢以檢索分配給Roles Users

我的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; }
}

編輯:查看問題中的代碼:沒有定義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})
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM