В EF у меня есть две таблицы (родительский Office- ребенок - Employee), я добавляю записи Employee со ссылкой на существующую запись Office, но я думаю, из-за моей неправильной конфигурации EF ведет себя изнуренным.
Вместо использования существующей записи таблицы Office она добавляет новые записи в Office и использует новый идентификатор записи в качестве внешнего ключа в дочерних записях, а затем создает дочерние записи.
Вот мои модели:
public class Office
{
public int OfficeId{ get; set; }
public string Name { get; set; }
public virtual IEnumerable<Employee> Employees{ get; set; }
}
public class Employee
{
public int EmployeeID{ get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
[NotMapped]
public int Age { get { return DOB.YearsFromUtcDateTillToday(); } }
[NotMapped]
public string FullName { get { return string.Concat(FirstName, ' ', LastName); } }
public virtual Office Office { get; set; }
}
Вид строго типизирован Employee
здесь - код просмотра:
@model Employee
@{
ViewBag.Title = "AddEmployee";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm(MVC.CodeTest.AddEmployee(),FormMethod.Post)) {
@Html.ValidationSummary(true)
@Html.HiddenFor(model=>model.Office.OfficID)
<fieldset>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.DOB)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DOB)
@Html.ValidationMessageFor(model => model.DOB)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.GPA)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.GPA)
@Html.ValidationMessageFor(model => model.GPA)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Мои действия контроллера следующие:
public virtual ActionResult AddEmployee(int officeId)
{
Employee st = new Employee();
st.Office=new Office();
st.Office.OfficeID= officeId;
return View(st);
}
[HttpPost]
public virtual ActionResult AddEmployee(Employee objEmployee)
{
bool success= classEmployeeService.AddEmployee(objEmployee);
if (success)
{
return RedirectToAction("Index",objEmployee.Office.OfficeId);
}
else
{
ModelState.AddModelError("", "Error! Business rule violation, can't repeat surname");
}
return View(objEmployee);
}
My Finding: В первом действии (без HttpPost) OfficeId верен, 1 в этом случае Проверка html Я узнал, что это правильно. Но при нажатии кнопки "Сохранить" выполняется второе действие с HttpPost. Значение OfficeId неверно, это новый идентификатор записи Office ( 18, 19 или следующей записи)
Пожалуйста, помогите мне.
Как я вижу, у вас проблемы с вашим дизайном модели. Класс Employee должен иметь свойство представлять внешний ключ OfficeID.
public class Employee
{
public int EmployeeID{ get; set; }
public int OfficeID{ get; set; } // This what you need
// ...... the rest of class properties
}
Затем просто присвойте идентификатору Office этому свойству не свойство навигации "Офис",
Employee st = new Employee();
st.OfficeID= officeId;
И никогда не используйте st.Office=new Office();
потому что это добавит этот объект в DbContext StateManager как "Добавлено" и добавит его в новую запись в базу данных.