【问题标题】:ef core many to many relation controlleref核心多对多关系控制器
【发布时间】:2021-02-09 09:50:34
【问题描述】:

我正在尝试使用 Entity Framework Core Database First 为用户和项目之间的多对多关系创建一个控制器。我使用脚手架从数据库创建模型。/ 创建/添加正在工作,但 CRUD 的其余部分没有(编辑,详细信息)。我怎样才能做到这一点?我做错了什么?

当我单击编辑或获取详细信息时,会出现此错误 错误: 找不到这个页面

用户项目表创建

CREATE TABLE [user_poject] (
    [user_id] INT , 
    [project_id] INT ,
    [user_roles] nvarchar(225)
    CONSTRAINT [user_project_PK] PRIMARY KEY ([user_id], [project_id]),

    CONSTRAINT fk_userProject_user
     FOREIGN KEY([user_id]) REFERENCES [user]([user_id]) ON DELETE CASCADE,

    CONSTRAINT fk_userProject_project 
     FOREIGN KEY([project_id]) REFERENCES [project]([project_id]) ON DELETE CASCADE
);

控制者:

public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var userPoject = await _context.UserPojects
                                   .Include(u => u.Project)
                                   .Include(u => u.User)
                                   .FirstOrDefaultAsync(m => m.UserId == id);
    if (userPoject == null)
    {
        return NotFound();
    }

    return View(userPoject);
}

// GET: UserPojects1/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var userPoject = await _context.UserPojects.FindAsync(id);
    if (userPoject == null)
    {
        return NotFound();
    }
    ViewData["ProjectId"] = new SelectList(_context.Projects, "ProjectId", "ProjectName", userPoject.ProjectId);
    ViewData["UserId"] = new SelectList(_context.Users, "UserId", "UserName", userPoject.UserId);
    return View(userPoject);
}

// POST: UserPojects1/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("UserId,ProjectId,UserRoles")] UserPoject userPoject)
{
    if (id != userPoject.UserId)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(userPoject);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!UserPojectExists(userPoject.UserId))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    ViewData["ProjectId"] = new SelectList(_context.Projects, "ProjectId", "ProjectName", userPoject.ProjectId);
    ViewData["UserId"] = new SelectList(_context.Users, "UserId", "UserName", userPoject.UserId);
    return View(userPoject);
}

用户项目模型:

public partial class UserPoject
{
    [Key]
    [Column("user_id" , Order =1)]
    public int UserId { get; set; }
    [Key]
    [Column("project_id" , Order =2)]
    public int ProjectId { get; set; }
    [Column("user_roles")]
    [StringLength(225)]
    public string UserRoles { get; set; }

    [ForeignKey(nameof(ProjectId))]
    [InverseProperty("UserPojects")]
    public virtual Project Project { get; set; }
    [ForeignKey(nameof(UserId))]
    [InverseProperty("UserPojects")]
    public virtual User User { get; set; }
}

用户模型:

  public partial class User
    {
        public User()
        {
            Tasks = new HashSet<Task>();
            UserPojects = new HashSet<UserPoject>();
            UserSprints = new HashSet<UserSprint>();
        }

        [Key]
        [Column("user_id")]
        public int UserId { get; set; }
        [Required]
        [Column("user_name")]
        [StringLength(50)]
        public string UserName { get; set; }
        [Column("user_email")]
        [StringLength(225)]
        public string UserEmail { get; set; }

        [InverseProperty(nameof(Task.User))]
        public virtual ICollection<Task> Tasks { get; set; }
        [InverseProperty(nameof(UserPoject.User))]
        public virtual ICollection<UserPoject> UserPojects { get; set; }
        [InverseProperty(nameof(UserSprint.User))]
        public virtual ICollection<UserSprint> UserSprints { get; set; }
    }

项目模型

 public partial class Project
    {
        public Project()
        {
            Sprints = new HashSet<Sprint>();
            UserPojects = new HashSet<UserPoject>();
        }

        [Key]
        [Column("project_id")]
        public int ProjectId { get; set; }
        [Column("project_name")]
        [StringLength(50)]
        public string ProjectName { get; set; }
        [Column("Project_description")]
        [StringLength(225)]
        public string ProjectDescription { get; set; }

        [InverseProperty(nameof(Sprint.Project))]
        public virtual ICollection<Sprint> Sprints { get; set; }
        [InverseProperty(nameof(UserPoject.Project))]
        public virtual ICollection<UserPoject> UserPojects { get; set; }
    }

DBContext-Fluent API


            modelBuilder.Entity<UserPoject>(entity =>
            {
                entity.HasKey(e => new { e.UserId, e.ProjectId })
                    .HasName("PK__user_poj__5279AEEECFA4D53D");

                entity.HasOne(d => d.Project)
                    .WithMany(p => p.UserPojects)
                    .HasForeignKey(d => d.ProjectId)
                    .HasConstraintName("FK__user_poje__proje__33D4B598");

                entity.HasOne(d => d.User)
                    .WithMany(p => p.UserPojects)
                    .HasForeignKey(d => d.UserId)
                    .HasConstraintName("FK__user_poje__user___32E0915F");
            });

【问题讨论】:

  • 请同时显示您的用户和项目类。
  • @Sergey 我加了他们
  • "create/Add 工作正常,但 CRUD 的其余部分没有工作" - 请更具体。什么不工作?它怎么不工作?有没有抛出异常?任何特定操作期间的任何错误消息?
  • @atiyar 已完成
  • 嗨@HagerHassan,你的意思是你已经解决了这个问题吗?如果是这种情况,请分享解决方案并接受它 - 请参阅What should I do when someone answers my question。它可以在未来帮助其他社区成员解决类似的问题。感谢您的理解。

标签: c# asp.net-core entity-framework-core


【解决方案1】:

当我单击编辑或获取详细信息时,此错误会出现错误: 找不到这个页面

public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var userPoject = await _context.UserPojects
                                   .Include(u => u.Project)
                                   .Include(u => u.User)
                                   .FirstOrDefaultAsync(m => m.UserId == id);
    if (userPoject == null)
    {
        return NotFound();
    }

    return View(userPoject);
}

正如我们之前讨论的,通过使用上面的代码,如果 id 为空,它将返回 NotFound 页面。因此,该问题与索引页面上的编辑和详细信息超链接有关。请参考以下代码(在ActionLink方法中,使用主键添加id参数):

@model IEnumerable<netcore5.Models.UserPoject>     
<table class="table">
    <thead>
           @*header*@
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.UserId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ProjectId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.UserRoles)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new {  id=item.UserId }) |
                @Html.ActionLink("Details", "Details", new {  id=item.UserId }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.UserId  })
            </td>
        </tr>
}
    </tbody>
</table>

另外,在 Startup.Configure 方法中,如果你使用的是默认的 MVC 路由模板,像这样:

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

            endpoints.MapRazorPages();
        });

然后,您还可以使用以下 Anchor Tag Helper 添加带有 id 参数的链接:

        <td>
            <a asp-action="Edit" asp-route-id="@item.UserId">Edit</a> |
            <a asp-action="Details" asp-route-id="@item.UserId">Details</a> |
            <a asp-action="Delete" asp-route-id="@item.UserId">Delete</a>
        </td>

结果如下:

参考:

Anchor Tag Helper in ASP.NET Core

Tutorial: Implement CRUD Functionality - ASP.NET MVC with EF Core

【讨论】:

    【解决方案2】:

    我看到了一些情况,首先您需要使用“PUT”而不是“POST”来进行更新操作。缓存策略将允许折叠冗余条目。此外,还有 PUT 的排序规则,而 POST 则没有。客户端以任何顺序发送 POST 操作并获得相同的结果应该是安全的。

    但是对于最初的问题,你会想要告诉上下文你已经修改了实体。

    来自Microsoft example

    // PUT: api/TodoItems/5
    [HttpPut("{id}")]
    public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
    {
        if (id != todoItem.Id)
        {
            return BadRequest();
        }
    
        _context.Entry(todoItem).State = EntityState.Modified;
    
        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!TodoItemExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
    
        return NoContent();
    }
    

    如果这仍然给您带来问题,请同时删除显式绑定,您可以使用属性正确装饰模型类。

    【讨论】:

    • 感谢您的重播,我都试过了,但仍然没有发现错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    相关资源
    最近更新 更多