实体框架代码首先有多个自定义用户和映射表

时间:2015-05-13 17:13:29

标签: c# entity-framework

我正在使用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想要存储新用户。我怎么解决这个问题?

亲切的问候

2 个答案:

答案 0 :(得分:2)

当您明确声明多对多关系实体时,您不需要使用FluentAPI设置任何内容。但是,您应分别从UserProject中删除以下行:

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. 用户管理(即管理允许访问您系统的用户)似乎与项目管理不同:

      

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

  2. 项目管理中,为了将用户分配给项目,似乎有一些特定于项目的其他信息需要作为{{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; 
        } 
    }
    
  3. 请注意,您可以使用简单查询为用户获取项目,而无需在模型中维护多对多关系:

    var user = ...;
    var projectsForUser =
        from project in db.Projects
        where project.MemberAssignments.Any(x => x.userId == user.UserId)
        select project;