如何从 asp.net MVC 中的数据库中删除具有两个主键的项目?

How do I delete an item from my database that has two primary keys in asp.net MVC?

大家好,我最近才开始接触 asp.net,但我还是个新手。我一直在做一个项目,但碰壁了。首先让我向您介绍我的项目的一些细节。我正在尝试创建一个具有一些功能的调度系统,其中一个功能是能够添加其他已注册为 "contacts" 的现有用户,您可以与之共享任务。

用户通过搜索现有用户的电子邮件来执行此操作,如果存在,他们可以将该用户添加为联系人。

现在我的问题来了。添加联系人后一切正常,但我无法删除它们。在删除操作 link 的索引视图中,我尝试同时使用 ContactUserId 和 ApplicationUserId 才意识到这不会起作用,因为它是一个关联 class 并且有两个主键。我的朋友很不愿意帮助我,建议我绑定两个主键,但我不知道该怎么做。请并感谢您的帮助。

控制器:

[Authorize]
public class ContactsController : Controller
{
    private ApplicationDbContext db = new ApplicationDbContext();

    // GET: Contacts
    public ActionResult Index()
    {

        IEnumerable<ApplicationUser> users = db.Users.ToList();

        IEnumerable<Contact> contacts = db.Contacts.ToList().Where(c =>     c.ApplicationUserID.Equals(User.Identity.Name));

        List<ApplicationUser> curUsers = new List<ApplicationUser>();

        foreach (var contact in contacts)
        {
            foreach (var user in users)
            {
                if (contact.ContactUserID.Equals(user.UserName))
                {
                    curUsers.Add(user);
                }
            }
        }

        ContactsViewModel cvm = new ContactsViewModel();
        cvm.users = curUsers;
        cvm.contacts = contacts;

        return View(cvm);
    }

    // GET: Contacts/Details/5
    public ActionResult Details(string id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Contact contact = db.Contacts.Find(id);
        if (contact == null)
        {
            return HttpNotFound();
        }
        return View(contact);
    }

    // GET: Contacts/Create
    public ActionResult Create()
    {
        return View();
    }

    // POST: Contacts/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 ActionResult Create([Bind(Include =     "ApplicationUserID,ContactUserID,Date")] Contact contact)
    {
        if (!String.IsNullOrWhiteSpace(contact.ContactUserID))
        {

            var count = db.Users.Count(u => u.UserName == contact.ContactUserID);

            if (count != 0)
            {
                contact.ApplicationUserID = User.Identity.Name;
                contact.Date = DateTime.Today; 
                db.Contacts.Add(contact);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            //User already exist error message                        
        }

        return View(contact);
    }

    // GET: Contacts/Edit/5
    public ActionResult Edit(string id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Contact contact = db.Contacts.Find(id);
        if (contact == null)
        {
            return HttpNotFound();
        }
        return View(contact);
    }

    // POST: Contacts/Edit/5
    // 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 ActionResult Edit([Bind(Include = "ApplicationUserID,ContactUserID,Date")] Contact contact)
    {
        if (ModelState.IsValid)
        {
            db.Entry(contact).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(contact);
    }

    // GET: Contacts/Delete/5
    public ActionResult Delete(string id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Contact contact = db.Contacts.Find(id);
        if (contact == null)
        {
            return HttpNotFound();
        }
        return View(contact);
    }

    // POST: Contacts/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public ActionResult DeleteConfirmed(string id)
    {
        Contact contact = db.Contacts.Find(id);
        db.Contacts.Remove(contact);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }
}

型号:

    public class Contact
{
    [Key]
    [Column(Order = 0)]
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string ApplicationUserID { get; set; }

    [Key]
    [Column(Order = 1)]
    [Display(Name = "Contact Email")]
    [Required (ErrorMessage = "Contact email is required")]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string ContactUserID { get; set; }

    public DateTime Date { get; set; }
}

索引视图:

@model MySchedule.ViewModels.ContactsViewModel

@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
@Html.ActionLink("Add", "Create")
</p>
<table class="table">
<tr>
    <th>
        <!--@@Html.DisplayNameFor(model => model.Date)-->
        First Name
    </th>
    <th>
        Last Name
    </th>
    <th>
        Email Name
    </th>
    <th></th>
</tr>
@{
var users = Model.users;
@foreach (var item in users)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Email)
        </td>
        <td>
            @Html.ActionLink("D", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("X", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr>
}
}
</table>

视图模型:

 public class ContactsViewModel
{
    public IEnumerable<ApplicationUser> users { get; set; }
    public IEnumerable<Contact> contacts { get; set; }

}

简短的回答是: 在 EF 中,如果您在实体中定义复合键,那么如果您想要使用 Find 来检索它,则必须提供您定义的所有键。在您的情况下,您需要以这种方式调用 Find:

Contact contact = db.Contacts.Find(applicationUserID, contactUserID);

以防您想要更多。按照以下步骤实现您想要的:

重构您的 GET 删除操作如下:

public ActionResult Delete(string applicationUserID, string contactUserID)
        {
            Contact contact = db.Contacts.Find(applicationUserID, contactUserID);
            if (contact == null)
                return HttpNotFound();

            return View(contact);
        }

重构您的 post 删除操作 (DeleteConfirmed) 还:

// POST: Contacts/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(string applicationUserID, string contactUserID)
        {
            Contact contact = db.Contacts.Find(applicationUserID, contactUserID);
            db.Contacts.Remove(contact);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

在您的 Index.cshtml 视图中生成 link 删除操作,如下所示:

@Html.ActionLink("X", "Delete", new { item.ApplicationUserID, item.ContactUserID })

这应该可以解决您的问题,但我认为您正在更改 属性 您正在循环播放的内容。也许你应该迭代 Model.contacts 而不是 Model.users?

希望对您有所帮助!