我正在使用WebAPI,EF Code First,并且遇到有关多对多关系的问题:
我正在使用继承自" 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&#34; UserManager&#34; &#34; FindById&#34;返回&#34; MyCustomUser&#34;。创建新的Users2Project-Class,向其添加新项目,将用户添加到其中失败,因为EF想要存储新用户。我怎么解决这个问题?
亲切的问候
答案 0 :(得分:2)
当您明确声明多对多关系实体时,您不需要使用FluentAPI设置任何内容。但是,您应分别从User
和Project
中删除以下行:
public virtual ICollection<Project> Projects { get; set; }
public virtual ICollection<MyCustomUser> Users { get; set; }
并添加两个实体:
public virtual ICollection<Users2Projects> Users2Projects { get; set; }
要为现有Project
添加新的User
,您可以:
var relation = new Users2Projects() {
User = existingUser, // reference retrieved from Context.
Project = new Project() { Title = "Project Alpha" }
}
Context.Users2Projects.Add(relation);
Context.SaveChanges();
据我所知,不可能强制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();
答案 1 :(得分:0)
尽管你实际上已经将它作为ProjectMemberAssignment
映射表进行了一些建模,但你在这里显然缺少一个概念实体。您可能想要解决应用程序中存在的aggregate root周围的一些概念,并再次查看您的要求
用户管理(即管理允许访问您系统的用户)似乎与项目管理不同:
因为无论用户是否有项目,用户都可以使用该应用程序。
在项目管理中,为了将用户分配给项目,似乎有一些特定于项目的其他信息需要作为{{1}的一部分进行捕获}。您的Project
似乎是这个有限上下文的{{3}},应该负责管理它的成员分配:
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;