繁体   English   中英

实体框架代码首先使用自定义用户和映射表进行多对多

[英]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进行任何设置。 但是您应该分别从UserProject删除以下几行:

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映射表,但您显然缺少这里的概念实体。 您可能需要围绕应用程序中存在的有限上下文来整理一些概念,然后再次查看您的需求

  1. 用户管理 (即,允许访问您的系统的用户的管理)似乎与项目管理不同:

    因为无论用户是否拥有项目,用户都可以使用该应用程序。

  2. 项目管理中 ,对于将用户分配给项目,似乎需要将特定于项目的其他信息作为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM