应用程序用户和其他表(实体)之间的关系

时间:2017-11-16 17:24:30

标签: c# asp.net-identity asp.net-core-2.0

我正在尝试将Application用户与UserTask应用程序表关联。但我得到了轰鸣声错误

InvalidOperationException:无法确定“UserTask”类型的导航属性“ApplicationUser.UserTask”所代表的关系。手动配置关系,或使用'[NotMapped]'属性或在'OnModelCreating'中使用'EntityTypeBuilder.Ignore'来忽略此属性

我使用的是NetCore 2.0.3

public class UserTask
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int UserTaskID { get; set; }

        public string Description { get; set; }

        [ForeignKey("OwnerUserID")]
        public string TaskOwnerId { get; set; }

        [ForeignKey("ExecutorUserID")]
        public string TaskExecutorId { get; set; }

        public virtual ApplicationUser OwnerUserID { get; set; }
        public virtual ApplicationUser ExecutorUserID { get; set; }
    }


 public class ApplicationUser : IdentityUser
    {
       [ForeignKey("UserTaskID")]
       public int UserTaskID { get; set; }

       public UserTask UserTask { get; set; }
    }

CONTROLER

public IActionResult Create()
        {
            ViewData["TaskOwnerId"] = new SelectList(_userManager.Users.ToList(), "Id", "Name");

            ViewData["TaskExecutorId"] = new SelectList(_userManager.Users.ToList(), "Id", "Name");

            return View();
        }

        // POST: UserTasks/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("UserTaskID,Description,TaskOwnerId,TaskExecutorId")] UserTask userTask)
        {
            if (ModelState.IsValid)
            {
                _context.Add(userTask);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            ViewData["TaskOwnerId"] = new SelectList(_userManager.Users.ToList(), "Id", "Name", userTask.TaskOwnerId);

            ViewData["TaskExecutorId"] = new SelectList(_userManager.Users.ToList(), "Id", "Name", userTask.TaskExecutorId);

            return View(userTask);
        }

和视图

<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Description" class="control-label"></label>
                <input asp-for="Description" class="form-control" />
                <span asp-validation-for="Description" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="TaskOwnerId" class="control-label"></label>
                 <select asp-for="TaskOwnerId" class="form-control" asp-items="ViewBag.TaskOwnerId"></select>
            </div>
            <div class="form-group">
                <label asp-for="TaskExecutorId" class="control-label"></label>
                <select asp-for="TaskExecutorId" class="form-control" asp-items="ViewBag.TaskExecutorId"></select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Description" class="control-label"></label>
                <input asp-for="Description" class="form-control" />
                <span asp-validation-for="Description" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="TaskOwnerId" class="control-label"></label>
                 <select asp-for="TaskOwnerId" class="form-control" asp-items="ViewBag.TaskOwnerId"></select>
            </div>
            <div class="form-group">
                <label asp-for="TaskExecutorId" class="control-label"></label>
                <select asp-for="TaskExecutorId" class="form-control" asp-items="ViewBag.TaskExecutorId"></select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>

你能帮帮我吗?

2 个答案:

答案 0 :(得分:0)

尝试

public class UserTask
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserTaskID { get; set; }

    public string Description { get; set; }

    public ApplicationUser ApplicationUser {get; set; }
}
public class ApplicationUser : IdentityUser
{
   public ICollection<UserTask> UserTask { get; set; }
}

在ApplicationDbContext类

protected override void OnModelCreating(ModelBuilder modelBuilder){
modelBuilder.Entity<ApplicationUser>()
    .HasMany(a => a.UserTask)
    .WithOne(b => b.ApplicationUser);}

答案 1 :(得分:0)

你的问题有两个方面:

  1. UserTask上只有ApplicationUser的一个导航属性。对于ApplicationUser上的UserTask,有两种不同的导航属性,EF无法将两种关系映射到另一侧的一个外键,因此如果您在一侧有两个导航属性,则需要两个也是另一个。例如:

    public UserTask OwnedUserTask { get; set; }
    public UserTask ExecutedUserTask { get; set; }
    
  2. 鉴于同一实体存在两种关系,EF并不知道UserTask上哪一个要映射到ApplicationUser上的哪一个,所以你&# 39;我必须配置这个:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>()
            .HasOne(x => x.OwnedUserTask)
            .WithOne(x => x.OwnerUser);
    
        modelBuilder.Entity<ApplicationUser>()
            .HasOne(x => x.ExecutedUserTask)
            .WithOne(x => x.ExecutorUser);
    }
    
  3. 那就是说,这是一对一并不是真的有意义。任务是你通常拥有的多个(如果我只有一个任务只执行一次!)。因此,这应该是一对多的,然后需要您将ApplicationUser更改为:

    public class ApplicationUser : IdentityUser
    {
       public ICollection<UserTask> OwnedUserTasks { get; set; }
       public ICollection<UserTask> ExecutedUserTasks { get; set; }
    }
    

    即使进行了更改,也存在与以前相同的问题:您与同一实体有两个关系,因此您必须添加配置以告知EF如何处理该问题。现在,您只能使用HasMany代替HasOne

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>()
            .HasMany(x => x.OwnedUserTasks)
            .WithOne(x => x.OwnerUser);
    
        modelBuilder.Entity<ApplicationUser>()
            .HasMany(x => x.ExecutedUserTasks)
            .WithOne(x => x.ExecutorUser);
    }
    

    最后,值得一提的是,你可以在关系的任何一方配置它。换句话说,您可以Entity<UserTask>然后HasOne(x => x.OwnerUser).WithMany(x => x.OwnedUserTasks)。这完全取决于你走哪条路。