В вопросе: нужен ли первичный ключ в таблице соединений?
У меня есть рабочий стол:
public partial class Job
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Job()
{
this.Room = new HashSet<Room>();
}
public int JobID { get; set; }
public string Title { get; set; }
public Nullable<int> DepartmentID { get; set; }
public virtual Department Department { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Room> Room { get; set; }
}
И пользовательская таблица:
public partial class AspNetUsers
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public AspNetUsers()
{
this.Department = new HashSet<Department>();
}
public string Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public Nullable<System.DateTime> LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Nullable<int> PhoneNo { get; set; }
public Nullable<System.DateTime> HireDate { get; set; }
public Nullable<System.DateTime> BirthDate { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Department> Department { get; set; }
}
Каждый пользователь может быть в нескольких отделах, и в каждом отделе может быть много пользователей.
В моем контроллере:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Praca.Models;
using Praca.ViewModels;
namespace Praca.Controllers
{
public class EmployeeController : Controller
{
private Entities1 db = new Entities1();
// GET: Employee
public ActionResult Index(string id)
{
var viewModel = new AspNetUserDepartmentVM();
viewModel.AspNetUsers = db.AspNetUsers
.Include(i => i.Department)
.OrderBy(i => i.LastName);
if (id != null)
{
ViewBag.EmployeeID = id;
viewModel.Departments = viewModel.AspNetUsers.Where(
i => i.Id == id).Single().Department;
}
return View(viewModel);
}
// GET: Employee/Details/5
public ActionResult Details(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
AspNetUsers aspNetUsers = db.AspNetUsers.Find(id);
if (aspNetUsers == null)
{
return HttpNotFound();
}
return View(aspNetUsers);
}
// GET: Employee/Create
public ActionResult Create()
{
return View();
}
// POST: Employee/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Email,EmailConfirmed,PasswordHash,SecurityStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEndDateUtc,LockoutEnabled,AccessFailedCount,UserName,FirstName,LastName,PhoneNo,HireDate,BirthDate")] AspNetUsers aspNetUsers)
{
if (ModelState.IsValid)
{
db.AspNetUsers.Add(aspNetUsers);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(aspNetUsers);
}
// GET: Employee/Edit/5
public ActionResult Edit(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
AspNetUsers aspNetUsers = db.AspNetUsers
.Include(i => i.Department)
.Where(i => i.Id == id)
.Single();
PopulateAssignedCourseData(aspNetUsers);
if (aspNetUsers == null)
{
return HttpNotFound();
}
return View(aspNetUsers);
}
private void PopulateAssignedCourseData(AspNetUsers aspNetUsers)
{
var allCourses = db.Department;
var instructorCourses = new HashSet<int>(aspNetUsers.Department.Select(c => c.DepartmentID));
var viewModel = new List<AssignedDepartment>();
foreach (var course in allCourses)
{
viewModel.Add(new AssignedDepartment
{
DepartmentID = course.DepartmentID,
DepartmentName = course.DepartmentName,
Assigned = instructorCourses.Contains(course.DepartmentID)
});
}
ViewBag.Courses = viewModel;
}
// POST: Employee/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(string id, string[] selectedCourses)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var instructorToUpdate = db.AspNetUsers
.Include(i => i.Department)
.Where(i => i.Id == id)
.Single();
if (TryUpdateModel(instructorToUpdate, "",
new string[] { "LastName"}))
{
try
{
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
PopulateAssignedCourseData(instructorToUpdate);
return View(instructorToUpdate);
}
private void UpdateInstructorCourses(string[] selectedCourses, AspNetUsers instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.Department = new List<Department>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.Department.Select(c => c.DepartmentID));
foreach (var course in db.Department)
{
if (selectedCoursesHS.Contains(course.DepartmentID.ToString()))
{
if (!instructorCourses.Contains(course.DepartmentID))
{
instructorToUpdate.Department.Add(course);
}
}
else
{
if (instructorCourses.Contains(course.DepartmentID))
{
instructorToUpdate.Department.Remove(course);
}
}
}
}
// GET: Employee/Delete/5
public ActionResult Delete(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
AspNetUsers aspNetUsers = db.AspNetUsers.Find(id);
if (aspNetUsers == null)
{
return HttpNotFound();
}
return View(aspNetUsers);
}
// POST: Employee/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(string id)
{
AspNetUsers aspNetUsers = db.AspNetUsers.Find(id);
db.AspNetUsers.Remove(aspNetUsers);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}`
К сожалению, у меня ошибка: невозможно обновить EntitySet 'AspNetUsersDepartment', так как он имеет DefiningQuery и в элементе нет элемента для поддержки текущей операции.
Как я могу решить эту проблему?
Когда я задаю первичный ключ для этой таблицы, отношения не многие со многими, а отношения два ко многим.