试着用EF6把头包裹在M:M附近。我有一个现有的数据库,我在代码中手动处理模型,使用模型创建的流畅API。
正如我已阅读并且对我而言,当db模式包含没有有效负载的联结表(额外字段)时,代表类不必是EF6模型的一部分。相反,M:M的每一端都有一个相反的集合,如下所示:
CREATE TABLE dbo.Personnel (
ID INT NOT NULL PRIMARY KEY CLUSTERED IDENTITY(1, 1),
CompanyID INT NOT NULL REFERENCES dbo.Company (ID) ON UPDATE CASCADE ON DELETE CASCADE,
PersonFirstName NVARCHAR(50) NOT NULL
-- etc etc
);
CREATE TABLE dbo.Roles (
ID INT NOT NULL PRIMARY KEY CLUSTERED IDENTITY(1, 1),
CompanyID INT NOT NULL REFERENCES dbo.Company (ID) ON UPDATE CASCADE ON DELETE CASCADE,
RoleName NVARCHAR(50) NOT NULL
-- etc etc
);
CREATE TABLE dbo.PersonnelRoles (
ID INT NOT NULL PRIMARY KEY CLUSTERED IDENTITY(1, 1),
RoleID INT NOT NULL REFERENCES dbo.Roles (ID) -- blah blah
PersonnelID INT NOT NULL REFERENCES dbo.Personnel(ID) -- blah blah
);
我设想我的模型如此:
public class Person()
{
public int ID {get;set;}
public int CompanyID {get;set;}
public string FirstName {get;set;}
public virtual Company Company {get;set;}
public virtual ICollection<Role> Roles {get;set;}
}
public class Role()
{
public int ID {get;set;}
public int CompanyID {get;set;}
public string Name {get;set;}
public virtual Company Company {get;set;}
public virtual ICollection<Person> Personnel {get;set;}
}
数据库联结表具有ID的代理主键。这足以摒弃EF模型不应该需要桥接类的概念吗?这个“ID”是否算作一个需要在代码中建模桥类的附加字段? (我真的希望避免这种情况,但外部约定意味着我必须按原样使用数据库模式。)
如果我已经做错了,我们可以跳过问题2,我会再次尝试使用桥类。
假设我实际上不需要类桥,并且我显示的两个模型是正确的,我如何使用流畅的API来设置正确的FK?当我尝试现在运行插入代码时,我得到以下内容:
保存未公开其关系的外键属性的实体时发生错误...
顶级异常建议的内部异常是:
无效的对象名称'dbo.RolePersons'
我的DbContext
看起来像这样:
public DbSet<Person> Personnel { get; set; }
public DbSet<Role> Roles { get; set; }
和OnModelCreating ......
modelBuilder.Entity<Person>().ToTable("Personnel");
modelBuilder.Entity<Person>().Property(e => e.FirstName).HasColumnName("PersonFirstName");
modelBuilder.Entity<Person>().Property(e => e.LastName).HasColumnName("PersonLastName");
modelBuilder.Entity<Person>().Property(e => e.Gender).HasColumnName("PersonGender");
modelBuilder.Entity<Role>().Property(e => e.Name).HasColumnName("RoleName");
modelBuilder.Entity<Role>().Property(e => e.Code).HasColumnName("RoleCode");
modelBuilder.Entity<Role>().Property(e => e.Description).HasColumnName("RoleDescription");
我查看了相关的问题和答案,并查看了HasRequired
和HasKey
,但我不确定如何在这里应用它们:表都不需要角色/人员在交界处,两个表中的任何一个都引用另一个表的键...
我可以在不需要桥接类的情况下对其进行建模,如果是这样,我该如何指示EF这样做?感谢。
答案 0 :(得分:1)
我相信你已经正确设置了一切。您得到的错误是因为EF期望连接表的名称是RolePersons,而不是PersonnelRoles。
要解决此问题,您必须在OnModelCreating中指定关系。您可以通过添加:
来完成此操作modelBuilder.Entity<Role>()
.HasMany(p => p.Personnel)
.WithMany(r => r.Roles)
.Map(r=> {
r.ToTable("PersonnelRoles");
r.MapLeftKey("RoleID");
r.MapRightKey("PersonnelID");
});