EntityFramework пытается вставить ноль, когда его просят сохранить ссылку на существующий объект в новом объекте. - PullRequest
1 голос
/ 03 февраля 2012

Я использую ASP.Net MVC3 и Entity Framework 4.

Сотрудник имеет OfficeLocation, который находится в другой таблице для нормализации.

У меня есть новый экран Сотрудника с раскрывающимся списком Расположение офиса:

<div class="editor-label">
    @Html.LabelFor(model => model.OfficeLocation.Id, "Office Location")
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.OfficeLocation.Id, new SelectList(ViewBag.OfficeLocations, "Id", "Name"))
    @Html.ValidationMessageFor(model => model.OfficeLocation.Id)
</div>

Это указывает на Id, потому что у меня были проблемы с получением привязки к работе. В моем контроллере я загружаю OfficeLocation из базы данных и сохраняю его в моем новом Employee перед сохранением. Я проверил значения на данный момент, и все правильно. Я также пытался Attach () employee.OfficeLocation, без изменений. employee.OfficeLocation не имеет нулевых значений, и его состояние не изменилось.

employee.OfficeLocation = db.OfficeLocations.Single(d => d.Id == employee.OfficeLocation.Id);
db.Employees.AddObject(employee);
db.SaveChanges();

И вот тогда я получаю исключение при вставке в OfficeLocations:

Cannot insert the value NULL into column 'Name', table 'test.HR.OfficeLocations'; column does not allow nulls. INSERT fails.
The statement has been terminated.

Я также попробовал обычный перезапуск Visual Studio, очистку сборки и так далее.

Обновление: когда я разрешил нулевые значения, я обнаружил, что он вставил в OfficeLocation строку со всеми нулевыми значениями, а затем использовал правильное значение в таблице Employee. Что.

Ответы [ 3 ]

0 голосов
/ 03 февраля 2012

Это то, что происходит, когда вы пытаетесь использовать модель данных в своем представлении. Вы действительно должны создавать собственные модели представлений, которые являются уникальными для вашей страницы, и на этой странице требуются только данные.

Тогда вы просто сделаете что-то вроде этого:

employee.OfficeLocationID = model.OfficeLocationID

Вы не устанавливаете OfficeLocation.ID, вы устанавливаете идентификатор в сущности сотрудника. OfficeLocation - это свойство навигации, которое перемещается к записи, указанной свойством OfficeLocationID вашего сотрудника.

0 голосов
/ 06 февраля 2012

Основной причиной моей проблемы было то, что при работе с IModelBinder я заставлял что-то в структуре генерировать новые OfficeLocations, которые содержали только (существующий) Id - который игнорируется EF при вставке, потому что у меня это с использованием SQL Идентификация поколения. Я решил это, позволив столбцам иметь нулевое значение и заметив, что он правильно устанавливает существующий идентификатор в таблице Employee, в то же время вставляя новую запись с нулевым именем в другую таблицу.

Таким образом, даже несмотря на то, что на новую сущность больше нигде не ссылались, среда пыталась вставить ее, когда я сохранил сущность Employee, которая изначально ссылалась на нее.

Надеюсь, кто-то еще выиграет от этого.

0 голосов
/ 03 февраля 2012

Не используйте Id при связывании этих двух объектов. Просто введите OfficeLocation типизированное свойство в свой класс Employee и связывайте новые офисные местоположения с вашими Employee экземплярами при каждом их создании. Нет необходимости чрезмерно усложнять, явно указав Id в вашем случае.

...