实体框架核心关系问题(代码优先) - 重复列
Posted
技术标签:
【中文标题】实体框架核心关系问题(代码优先) - 重复列【英文标题】:Entity Framework Core Relationship Issue (code first) - duplicate columns 【发布时间】:2021-11-02 11:45:27 【问题描述】:我正在使用代码优先方法(EF Core 5 + SQL Server)开发一个应用程序。
我有一些包含数据的表,然后是 2 个连接表。
我遇到的问题是 EF 以某种方式在连接表中创建了重复的列。例如。 SessionId 和 SessionId1。我不知道为什么。
这里有一些来自代码的sn-ps以便更好地理解:
会话表:
public class Session
public long Id get; set;
public string Name get; set;
public long EventId get; set;
public virtual Event Event get; set;
public virtual UserSessionRole UserSessionRole get; set;
事件表:
public class Event
public long Id get; set;
public string Name get; set;
public DateTime Date get; set;
public virtual List<Session> Sessions get; set;
连接表:
public class UserSessionRole
public long Id get; set;
public long SessionId get; set;
public long RoleId get; set;
public long UserId get; set;
public long EventId get; set;
public virtual Session Session get; set;
public virtual Event Event get; set;
public virtual Role Role get; set;
public virtual User User get; set;
我使用 fluent API 来定义关系等。例如。会话设置:
// Map entities to tables
modelBuilder.Entity<Session>().ToTable("sessions");
// Configure Primary Keys
modelBuilder.Entity<Session>().HasKey(u => u.Id);
modelBuilder.Entity<Session>().Property(p => p.Id).ValueGeneratedOnAdd();
// Configure indexes
modelBuilder.Entity<Session>().HasIndex(u => u.EventId);
// Configure columns
modelBuilder.Entity<Session>().Property(ug => ug.Name).HasColumnType("nvarchar(255)").IsRequired();
modelBuilder.Entity<Session>().Property(ug => ug.Description).HasColumnType("nvarchar(255)").IsRequired();
modelBuilder.Entity<Session>().Property(ug => ug.DateTime).HasColumnType("datetime").IsRequired();
modelBuilder.Entity<Session>().Property(ug => ug.VonageSessionId).HasColumnType("nvarchar(255)").IsRequired();
// Configure relationships
modelBuilder.Entity<Session>().HasMany<UserSessionRole>().WithOne(r => r.Session).HasForeignKey(u => u.SessionId).OnDelete(DeleteBehavior.NoAction);
用户会话角色:
// Map entities to tables
modelBuilder.Entity<UserSessionRole>().ToTable("usersessionroles");
// Configure Primary Keys
modelBuilder.Entity<UserSessionRole>().HasKey(x => new x.RoleId, x.SessionId, x.UserId );
modelBuilder.Entity<UserSessionRole>().Property(p => p.Id).ValueGeneratedOnAdd();
在这种情况下,我得到重复的 SessionId 和重复的 RoleId,但不是 EventId。
任何人都知道我配置错了什么或者是否有任何我不知道的技巧?
【问题讨论】:
【参考方案1】:我最终通过从 Session 中删除 Event 并明确定义 WithMany 关系解决了这个问题。我也是从另一边做的。
这行得通:
modelBuilder.Entity<UserSessionRole>().HasOne(x => x.Event).WithMany(s => s.UserSessionRoles).HasForeignKey(u => u.EventId).OnDelete(DeleteBehavior.NoAction);
这没有:
modelBuilder.Entity<UserSessionRole>().HasOne(x => x.Event).WithMany(s).HasForeignKey(u => u.EventId).OnDelete(DeleteBehavior.NoAction);
【讨论】:
【参考方案2】:使用您的代码 sn-p 我可以理解的是您正在尝试创建一对多关系的事件和会话表,如果是这样我们可以避免连接表 (UserSessionRole) 并将 RoleId、UserId 带到会话表。
public class Event
public long Id get; set;
public string Name get; set;
public DateTime Date get; set;
public virtual ICollection<Session> Sessions get; set;
public class Session
public long Id get; set;
public string Name get; set;
public long RoleId get; set;
public long UserId get; set;
public long EventId get; set;
public virtual Event Event get; set;
public virtual Role Role get; set;
public virtual User User get; set;
如果你需要连接表(UserSessionRole)那么关系变成Event : UserSessionRole(一对多)和UserSessionRole : Session(一对一)就会变成这样,
public class Event
public long Id get; set;
public string Name get; set;
public DateTime Date get; set;
public virtual ICollection<UserSessionRole>SessionRoles get; set;
// One to Many Relation between Event and UserSessionRole
public class UserSessionRole
public long Id get; set;
public long EventId get; set;
public long RoleId get; set;
public long UserId get; set;
public long SessionId get; set;
public virtual Session Session get; set;
public virtual Event Event get; set;
public virtual Role Role get; set;
public virtual User User get; set;
// One to One Relation between UserSessionRole and Session
public class Session
public long Id get; set;
public string Name get; set;
public virtual Session Session get; set;
【讨论】:
【参考方案3】:由于你有连接表并且在 Session 和 Event 之间建立了多对多关系,所以从 Session 中移除 EventId,并且由于你使用的是 Net5,你也可以将事件集合添加到 Session 中
public class Session
public long Id get; set;
public string Name get; set;
public virtual ICollection<Event> Events get; set;
public virtual ICollection <UserSessionRole> UserSessionRoles get; set;
Event table:
public class Event
public long Id get; set;
public string Name get; set;
public DateTime Date get; set;
public virtual ICollection <UserSessionRole> UserSessionRoles get; set;
public virtual List<Session> Sessions get; set;
【讨论】:
我试过了,但没有解决问题,谢谢。 @Skynet 你必须相应地更新你的 Fluent API 并再次进行初始化迁移。以上是关于实体框架核心关系问题(代码优先) - 重复列的主要内容,如果未能解决你的问题,请参考以下文章