如何使用实体框架在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查询来检索分配给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})
}