我试图在Jimmy Bogard中遵循这个想法,避免在ORM中避免多对多映射
鉴于此设置,我希望能够直接公开'加入'关系中的对象。
物件
代码:
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class Role
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class UserRole
{
public Guid UserId { get; set; }
public Guid RoleId { get; set; }
public User User { get; set; }
public Role Role { get; set; }
}
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.Entity<UserRole>().HasKey(u => new { u.RoleId, u.UserId });
modelBuilder.Entity<User>().HasMany(x => x.Roles).WithMany(x => x.Users).Map(m =>
{
m.ToTable("UserRoles");
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
});
}
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
//public DbSet<UserRole> UserRoles { get; set; }
}
如果我为此添加迁移,我会得到我期望的结果。
public override void Up()
{
CreateTable(
"dbo.Roles",
c => new
{
Id = c.Guid(nullable: false),
Name = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Users",
c => new
{
Id = c.Guid(nullable: false),
Name = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.UserRoles",
c => new
{
UserId = c.Guid(nullable: false),
RoleId = c.Guid(nullable: false),
})
.PrimaryKey(t => new { t.UserId, t.RoleId })
.ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true)
.ForeignKey("dbo.Roles", t => t.RoleId, cascadeDelete: true)
.Index(t => t.UserId)
.Index(t => t.RoleId);
}
我将一个DBset添加到UserRoles对象的DbContext中。 EF无法找到UserRoles对象的PK。
UserRoles:EntityType:EntitySet&#39; UserRoles&#39;基于类型&#39; UserRole&#39;没有定义键。
然后我尝试像这样指定Key:
modelBuilder.Entity<UserRole>().HasKey(u => new { u.RoleId, u.UserId });
但EF并不知道我想使用相同的UserRoles表,因为它为该对象添加了第二个表。
CreateTable(
"dbo.UserRoles1",
c => new
{
RoleId = c.Guid(nullable: false),
UserId = c.Guid(nullable: false),
})
.PrimaryKey(t => new { t.RoleId, t.UserId })
.ForeignKey("dbo.Roles", t => t.RoleId, cascadeDelete: true)
.ForeignKey("dbo.Users", t => t.UserId, cascadeDelete: true)
.Index(t => t.RoleId)
.Index(t => t.UserId);
如何指示我只想使用单个UserRole表的DbModelBuilder?
我在github
上有针对此问题的演示.sln答案 0 :(得分:2)
我认为你把两件事混在一起。
如果要公开M:N
表,则不能在实体框架中使用M:N
关联,因为实体框架会为您隐藏它。然后,您应该将其映射为两个1:M
和N:1
关联。在这种情况下,您强制实体框架以这种方式思考,而不是M:N
。当您自己查询此关联时,您必须指定所有条件(这可能是您想要做的事情)。基本上是为了代表您加入实体框架。
但你也可以同时使用这两个世界。虽然它可能很危险,但您必须仔细进行更新,删除等操作。您可以创建一个仅MyUserRoles
的{{1}}视图,并将其映射为select * from UserRoles
实体的后备“表” 。但正如我所说,你应该对变化非常小心,因为你可能很容易通过改变UserRoles
来混淆DbContext
,而实体框架认为MyUserRoles
没有变化。