[英]Entity Framework Code First Many to Many with Custom User and Mapping Table
我正在使用EF Code First和WebAPI,并且存在关于多对多关系的问题:
我正在与从“ IdentityUser”继承的自定义用户一起使用,该用户可以有多个项目。
这些项目现在可以有多个用户。 除此之外,我想在映射表中存储其他字段。
public class MyCustomUser : IdentityUser
{
// blah blah...
public virtual ICollection<Project> Projects { get; set; }
}
public class Project
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<MyCustomUser> Users { get; set; }
}
public class Users2Projects
{
public int UserId { get; set; }
public int ProjectId { get; set; }
public virtual MyCustomUser User { get; set; }
public virtual Project Project { get; set; }
public string AdditionalField1 {get;set;}
public string AdditionalField1 {get;set;}
}
问题是:我必须如何设置关系(FluentAPI)才能为已经存在的用户插入项目? 因为无论用户是否拥有项目,用户都可以使用该应用程序。
因此,用户可以有一个项目,但是一个项目必须至少有一个用户。 我正在通过Owin“ UserManager”“ FindById”获取用户,该用户返回“ MyCustomUser”。 创建新的Users2Project-Class,向其中添加新项目,向其中添加用户失败,因为EF希望存储新用户。 我该如何解决?
亲切的问候
当您显式声明多对多关系实体时,无需使用FluentAPI进行任何设置。 但是您应该分别从User
和Project
删除以下几行:
public virtual ICollection<Project> Projects { get; set; }
public virtual ICollection<MyCustomUser> Users { get; set; }
并添加两个实体:
public virtual ICollection<Users2Projects> Users2Projects { get; set; }
要为现有User
添加新Project
,您可以:
var relation = new Users2Projects() {
User = existingUser, // reference retrieved from Context.
Project = new Project() { Title = "Project Alpha" }
}
Context.Users2Projects.Add(relation);
Context.SaveChanges();
据我所知,不可能在Entity Framework上使用显式关系类来强制Project
具有至少一个User
,因此在将Project
插入Context
时,您必须以编程方式进行检查:
if (project.Users2Projects.Count() == 0)
throw new Exception("Project must have at least one user.")
Context.Projects.Add(project);
Context.SaveChanges();
并且在删除User
在此之前的检查:
var projectsToDelete = new List<Project>();
foreach (var relationship in user.Users2Projects)
{
if (relationship.Project.Users2Projects.Count() <= 1)
projectsToDelete.Add(relationship.Project);
}
Context.MyCustomUsers.Remove(user);
Context.Projects.RemoveRange(projectsToDelete);
Context.SaveChanges();
尽管您实际上已经将其建模为Users2Projects
映射表,但您显然缺少这里的概念实体。 您可能需要围绕应用程序中存在的有限上下文来整理一些概念,然后再次查看您的需求
用户管理 (即,允许访问您的系统的用户的管理)似乎与项目管理不同:
因为无论用户是否拥有项目,用户都可以使用该应用程序。
在项目管理中 ,对于将用户分配给项目,似乎需要将特定于项目的其他信息作为ProjectMemberAssignment
一部分进行捕获。 您的Project
似乎是此有限上下文的聚合根 ,并应负责管理其成员分配:
public class Project { public virtual int Id { get; private set; } public string Title { get; set; } public void AssignMember(int userId, string someField, string someOtherField) { if (MemberAssignments.Any(x => x.UserId == userId)) throw new InvalidOperationException("User already assigned"); MemberAssignments.Add(new ProjectMemberAssignment(Id, userId, someField, someOtherField)); } // Other behavior methods. public virtual ICollection<ProjectMemberAssignment> MemberAssignments { get; set; } }
请注意,您可以使用简单的查询为用户获取项目,而无需在模型中保持多对多关系:
var user = ...;
var projectsForUser =
from project in db.Projects
where project.MemberAssignments.Any(x => x.userId == user.UserId)
select project;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.