如何从 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
?
希望对您有所帮助!
大家好,我最近才开始接触 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
?
希望对您有所帮助!