我有以下用于EFCodeFirst数据库创建的C#代码:
enum MemberOfGroupDiscriminator { MemberOfGroup, GroupMemberOfGroup, UserMemberOfGroup }
public class MemberOfGroup
{
public int Member_ID { get; set; }
public int Group_ID { get; set; }
}
public class GroupMemberOfGroup : MemberOfGroup { }
public class UserMemberOfGroup : MemberOfGroup { }
public class User : WSSCSDevModel, IUser
{
public int LoginCount { get; set; }
public DateTime LastLogin { get; set; }
public virtual ICollection<MemberOfGroup> Memberships { get; set; }
}
public class Group : WSSCSDevModel, IGroup
{
public string Name { get; set; }
}
这在用于创建数据库的流畅API中:
ModelBuilder.Entity<MemberOfGroup>()
.HasKey(k => new { k.Member_ID, k.Group_ID })
.Map<MemberOfGroup>(m => m.Requires("OfGroupType")
.HasValue((byte)MemberOfGroupDiscriminator.MemberOfGroup))
.Map<UserMemberOfGroup>(m => m.Requires("OfGroupType")
.HasValue((byte)MemberOfGroupDiscriminator.UserMemberOfGroup))
.Map<UserMemberOfGroup>(m => m.Properties(p => p.Member_ID = UserAddition.))
.Map<GroupMemberOfGroup>(m => m.Requires("OfGroupType")
.HasValue((byte)MemberOfGroupDiscriminator.GroupMemberOfGroup))
.ToTable("MemberOfGroup");
我的想法是允许用户和群组能够组建群组。所以GroupB可以是GroupA加上另外一个人。我的问题是,当判别式出现时,我如何强制框架检查Member_ID是否是User的关键,以及Group。
BTW,用户和组实体具有int ID {get;组;在他们的父类中声明。
谢谢!
编辑:
重新审视此问题,我现在遇到了向群组添加成员的问题。这是我的代码:
public class WSSCSDevDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Group> Groups { get; set; }
protected override void OnModelCreating(DbModelBuilder ModelBuilder)
{
ModelBuilder.Entity<User>().ToTable("Users");
ModelBuilder.Entity<Group>().ToTable("Groups");
ModelBuilder.Entity<MemberOfGroup>()
.HasKey(m => m.ID)
.Map<GroupMemberOfGroup>(g => g.Requires("OfType")
.HasValue((byte)MemberOfGroupDiscriminator.GroupMemberOfGroup))
.Map<UserMemberOfGroup>(u => u.Requires("OfType")
.HasValue((byte)MemberOfGroupDiscriminator.UserMemberOfGroup));
ModelBuilder.Entity<User>()
.HasMany(u => u.MemberOf)
.WithRequired(m => m.MemberUser)
.HasForeignKey(m => m.MemberUser_ID)
.WillCascadeOnDelete(false);
ModelBuilder.Entity<Group>()
.HasMany(g => g.MemberOf)
.WithRequired(m => m.MemberGroup)
.HasForeignKey(m => m.MemberGroup_ID)
.WillCascadeOnDelete(false);
ModelBuilder.Entity<Group>()
.HasMany(u => u.Members)
.WithRequired(m => m.Group)
.HasForeignKey(m => m.Group_ID);
}
}
public class User : WSSCSDevModel, IUser
{
public int LoginCount { get; set; }
public DateTime LastLogin { get; set; }
public virtual ICollection<UserMemberOfGroup> MemberOf { get; set; }
public virtual ICollection<MemberOfGroup> Memberships { get; set; }
}
public class Group : WSSCSDevModel, IGroup
{
public string Name { get; set; }
public virtual ICollection<GroupMemberOfGroup> MemberOf { get; set; }
public virtual ICollection<MemberOfGroup> Members { get; set; }
}
public class MemberOfGroup
{
public int? Group_ID { get; set; }
virtual public Group Group { get; set; }
}
public class GroupMemberOfGroup : MemberOfGroup
{
public int? MemberGroup_ID { get; set; }
virtual public Group MemberGroup { get; set; }
}
public class UserMemberOfGroup : MemberOfGroup
{
public int? MemberUser_ID { get; set; }
virtual public User MemberUser { get; set; }
}
同样,Group和User父类定义了int ID {get; set;}
以下是我的控制器中将用户添加到群组的代码:
if(model.MemberOf_IDs != null)
{
Repository<User> UserRepo = new Repository<User>();
User ToEdit = UserRepo.GetById(model.User_ID);
foreach (UserMemberOfGroup Membership in ToEdit.MemberOf)
{
Membership.Group.Members.Remove(Membership);
}
ToEdit.MemberOf = new List<UserMemberOfGroup>();
Repository<Group> GroupRepo = new Repository<Group>();
string[] Delims = new string[1];
Delims[0] = ";";
List<int> IDs = model.MemberOf_IDs.Split(Delims,
StringSplitOptions.RemoveEmptyEntries).Select(id => Convert.ToInt32(id)).ToList();
foreach(int ID in IDs)
{
Group ToAddTo = GroupRepo.GetById(ID);
ToEdit.MemberOf.Add(ToAddTo.AddMember(ToEdit));
}
GroupRepo.Save();
}
我知道这甚至都不是最好的方法,但它说明了我的问题。 BTW,存储库&lt;&gt;类共享DBContext。所以基本上,。保存在一个是。保存所有。这工作正常。
此代码采用以分号分隔的组ID字符串,并将User添加到它们中。但是,我得到了这个例外:
A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Cannot insert the value NULL into column 'Group_ID', table 'CSProSuiteIndia.dbo.MemberOfGroups'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
我不明白为什么要将Group_ID更改为NULL。我将Group_ID声明为int?,所以它应该是可以为空的,我想。这里发生了什么?
答案 0 :(得分:1)
您想要的是动态切换用户和组之间的外键引用。你能在单列数据库中做到这一点吗?你不能,所以你也不能在ORM中这样做。
如果要强制执行完整性,则必须将Member_ID
从父级移动到子级并为其映射单独的关系。它将在db中创建两列,每列都有自己的FK:
public abstract class Principal
{
public int Id { get; set; }
}
public class User : Principal
{
public string Login { get; set; }
public virtual ICollection<UserMemberOfGroup> MemberOf { get; set; }
}
public class Group : Principal
{
public string Name { get; set; }
public virtual ICollection<GroupMemberOfGroup> MemberOf { get; set; }
public virtual ICollection<MemberOfGroup> Members { get; set; }
}
public enum MemberOfGroupDiscriminator
{
MemberOfGroup,
GroupMemberOfGroup,
UserMemberOfGroup
}
public abstract class MemberOfGroup
{
public int Id { get; set; }
public int GroupId { get; set; }
public Group Group { get; set; }
}
public class GroupMemberOfGroup : MemberOfGroup
{
public int MemberGroupId { get; set; }
public Group MemberGroup { get; set; }
}
public class UserMemberOfGroup : MemberOfGroup
{
public int UserId { get; set; }
public User User { get; set; }
}
public class Context : DbContext
{
public DbSet<Principal> Principals { get; set; }
public DbSet<MemberOfGroup> MembersOfGroups { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Principal>()
.HasKey(p => p.Id)
.Map<User>(u => u.Requires("Type").HasValue("U"))
.Map<Group>(p => p.Requires("Type").HasValue("G"));
modelBuilder.Entity<MemberOfGroup>()
.HasKey(m => m.Id)
.Map<GroupMemberOfGroup>(g => g.Requires("Type").HasValue("G"))
.Map<UserMemberOfGroup>(u => u.Requires("Type").HasValue("U"));
modelBuilder.Entity<User>()
.HasMany(u => u.MemberOf)
.WithRequired(m => m.User)
.HasForeignKey(m => m.UserId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Group>()
.HasMany(u => u.MemberOf)
.WithRequired(m => m.MemberGroup)
.HasForeignKey(m => m.MemberGroupId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Group>()
.HasMany(u => u.Members)
.WithRequired(m => m.Group)
.HasForeignKey(m => m.GroupId);
}
}