"传递的主键值的数量必须与实体上定义的主键值的数量相匹配。参数名称:keyValues"实体框架

时间:2015-02-23 09:46:22

标签: c# asp.net sql-server asp.net-mvc entity-framework

所以我在ASP.NET MVC应用程序中使用了Entity Framework的CRUD操作。我已经创建了一个登录表单,其中每个唯一用户都获得了UserId,我现在尝试操作这些CRUD操作,以便用户可以编辑或删除它的数据库记录。但是我会在标题中看到错误。

我认为它与我的主键有关,这里有一些代码:

型号:

public partial class TimesheetEntry
    {
        [Key]
        [Column(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int UserId { get; set; }

        [Key]
        [Column(Order = 1)]
        [StringLength(50)]
        public string ProjectId { get; set; }

        [Key]
        [Column(Order = 2, TypeName = "date")]
        public DateTime EntryDate { get; set; }

        public decimal HoursWorked { get; set; }

        public virtual Project Project { get; set; }

        public virtual User User { get; set; }
    }

查看:

@model IEnumerable<Aviato.Models.TimesheetEntry>

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.UserId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Project.ProjectName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.EntryDate)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.HoursWorked)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.UserId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Project.ProjectName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EntryDate)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.HoursWorked)
            </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>
    }

</table>
<div>
    @Html.ActionLink("Index", "Index", "User")
</div>

控制器:

public class TimesheetEntryController : Controller
    {
    private readonly AviatoModel _db = new AviatoModel(); //Database Model

    public ActionResult Edit(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }

                var timesheetentry = _db.TimesheetEntries.Find(id);

                if (timesheetentry == null)
                {
                    return HttpNotFound();
                }

                ViewBag.ProjectId = new SelectList(_db.Projects, "ProjectId", "ProjectName", timesheetentry.ProjectId);
                ViewBag.UserId = new SelectList(_db.Users, "UserId", "SocialSecurityNumber", timesheetentry.UserId);

                return View(timesheetentry);
            }

            [HttpPost]
            public ActionResult Edit([Bind(Include="UserId,ProjectId,EntryDate,HoursWorked")] TimesheetEntry timesheetentry)
            {
                if (ModelState.IsValid)
                {
                    _db.Entry(timesheetentry).State = System.Data.Entity.EntityState.Modified;
                    _db.SaveChanges();
                    return RedirectToAction("Index");
                }

                ViewBag.ProjectId = new SelectList(_db.Projects, "ProjectId", "ProjectName", timesheetentry.ProjectId);
                ViewBag.UserId = new SelectList(_db.Users, "UserId", "SocialSecurityNumber", timesheetentry.UserId);

                return View(timesheetentry);
            }
}

数据库表:

CREATE TABLE [dbo].[TimesheetEntries] (
    [UserId]      INT            NOT NULL,
    [ProjectId]   NVARCHAR (50)  NOT NULL,
    [EntryDate]   DATE           NOT NULL,
    [HoursWorked] DECIMAL (8, 1) CONSTRAINT [DF_TimesheetEntries_HoursWorked] DEFAULT ((0.0)) NOT NULL,
    CONSTRAINT [PK_TimesheetEntries] PRIMARY KEY CLUSTERED ([UserId] ASC, [ProjectId] ASC, [EntryDate] ASC),
    CONSTRAINT [FK_TimesheetEntries_Users] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users] ([UserId]),
    CONSTRAINT [FK_TimesheetEntries_Projects] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Projects] ([ProjectId])
);

那么,如何让用户在数据库中更改自己的唯一数据呢?

请帮忙。

2 个答案:

答案 0 :(得分:2)

冲突的陈述是

var timesheetentry = _db.TimesheetEntries.Find(id);

正如您所正确提到的,它与关键字段的数量有关。如果您的模型必须将三个元素传递给Find()

所以你必须

  1. 将所有三个元素传递到Edit()操作或
  2. 拥有一个只有一列的唯一键(即一个分离键元素 - 在您的方法中不是首选)

答案 1 :(得分:1)

通常,当您收到此异常时,表示您要求通过其主键(或键组)查找特定实体。

如果您确定.Find()方法的参数是正确的主键数,请检查您的edmx模型是否显示正确数量的主键。

如果你的edmx模型是正确的,那么错误只会出现在你的数据库本身的另一个地方。检查数据库并确保在实际表中实际设置了任何主键。

  

如果您的数据库表没有指定主键字段,则您的edmx将假定每个字段都是键。因此,请确保您的数据库和实体模型说同样的事情。