ASP.Net MVC + привязка модели LINQ to SQL, сохранение сложного дочернего объекта после публикации - PullRequest
1 голос
/ 05 января 2011

У меня есть форма ASP.Net MVC «Создать нового сотрудника».

Мой сложный объект - Сотрудник , а Сотрудник имеет Адрес , который является другим сложным объектом.

В моем представлении / форме я собираю все необходимые значения как для сотрудника, так и для адреса.

Я использую связанные помощники HTML, такие как:

Html.TextBoxFor(model => model.EmployeeAddress.StreetName)

И

Html.TextBoxFor(model => model.NewEmployee.FirstName)

и т.д.

Все это прекрасно работает. Привязка модели работает как мечта, проверка как на стороне сервера, так и на стороне клиента с использованием DataAnnotations работает прекрасно, и я приятно получаю заполненные сложные объекты, как и ожидалось в контроллере.

Теперь я пытаюсь сохранить ..

  • Сотрудник должен всегда создаваться заново, потому что это форма «Добавить нового сотрудника».
  • Но иногда адрес - это существующий адрес, и я не хочу вставлять другой.
  • Скорее, я просто хочу связать Сотрудника с существующим AddressID того, который уже существует в базе данных.

Итак, я написал изящный метод GetExistingOrCreateNewAddress (Address PostedAddress), который прекрасно работает, поэтому я получаю правильный адрес для использования и ссылку на , который собирается сохранить объект Employee. Все это происходит в одном и том же DataContext, так что проблем нет ..

НО, даже когда я связываю , который должен быть сохранен Объект Employee с существующим адресом, при сохранении новая / пустая строка адреса создается в моей таблице адресов. Несмотря на то, что вновь созданный Сотрудник правильно связывается с существующим адресом, на который я ему указал!

Почему это так ??? И как я могу сохранить нового сотрудника без LINQ, автоматически создавая пустой адрес для меня. Поскольку я явно указываю существующий адрес, он должен быть связан вместо этого!

Вот так выглядит мой контроллер:

    [HttpPost]
    public ActionResult CreateEmployee(EmployeeDetailsViewModel NewEmployeeDetails)
    {
        if (ModelState.IsValid)
        {
            EmployeeRepository ER = new EmployeeeRepository();

            // Fetch or Create the appropriate Address object for what has been entered
            Address ActualAddress = ER.GetExistingOrCreateNewAddress(NewEmployeeDetails.EnteredAddress);

            // Link this Address to the "about to be saved" Employee
            NewEmployeeDetails.Employee.Address = ActualAddress;

            // Lock it in..
            ER.SaveNewEmployee(NewEmployeeDetails.Employee);

Я не получаю никаких ошибок!

Может кто-нибудь объяснить ??

Ответы [ 2 ]

0 голосов
/ 06 января 2011

Я понял это.

Внутри моего сложного объекта Address он также имеет еще один дочерний сложный объект, который называется "Suburb". Я собирался в базу данных в том же DataContext и выбирал соответствующий объект Suburb для присоединения к моему объекту Address.

Все это делалось внутри собственного метода в моем классе хранилища данных.

Даже после того, как позднее обнулить тот же адрес и присвоить его значение SomeExistingAddress, привязка LINQ или модели все еще чувствовала необходимость создания пустого адреса. Это было связано с тем, что ранее я связывал выбранную выше запись Suburb (прикрепленную к базе данных, не использовал ToList ()) с отдельным / локальным объектом Address. В результате, нравится мне это или нет, LINQ чувствовал, что теперь необходимо создать пустой новый (но с Первичным ключом) объект Address, потому что связанный Suburb должен был принадлежать чему-то, что было ранее отсоединено. Я надеюсь, что в этом есть смысл. Таким образом, мое решение состояло в том, что при извлечении Пригорода для заполнения в Адрес, который, в свою очередь, должен был заполнить Сотрудника, мне нужно было убедиться, что я выбрал Пригород с помощью ToList (), прежде чем выполнить этот запрос, чтобы найти правильный. Без ToList () он ожидал, что мне понадобится заново создать родительскую сущность даже после обнуления.

Действительно странно, и я пока не до конца понимаю, но вроде как. Мой урок:

"Когда необходимо заполнить значения дочернего сложного объекта отдельного / локального родительского сложного объекта, убедитесь, что вы только прикрепили другие отключенные объекты, но никогда не присоединяйте предварительно прикрепленные. Поскольку LINQ принудительно создаст пустую копию сложного родительского объекта просто потому что он отсоединен от базы данных, а его дочерний объект - нет, поэтому он считает, что ему нужно вставить новый экземпляр родительского объекта. Вместо этого просто все время работать локально / отсоединять и сразу отправлять SubmitChanges.

Это был старый сломанный код:

FauxAddress.Suburb = db.Suburbs.Where(x => x.SuburbName == FauxAddress.Suburb.SuburbName && x.Postcode == FauxAddress.Suburb.Postcode).FirstOrDefault();

Это новый / разрешенный код:

FauxAddress.Suburb = db.Suburbs.ToList().Where(x => x.SuburbName == FauxAddress.Suburb.SuburbName && x.Postcode == FauxAddress.Suburb.Postcode).FirstOrDefault();
0 голосов
/ 05 января 2011

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

Ты этого хочешь?Может быть, ошибка на самом деле является функцией?

P никогда не запрашивают указатели :)


Нет, моя система и логика не работают так.Если мой сотрудник изменяет свой адрес, моя система переходит и создает для него еще одну новую запись адреса.Адреса - это все физические адреса, если адрес изменяется, то это считается другим совершенно другим физическим адресом и, следовательно, другой записью.Я уже справился с этим.

тогда каково преимущество уникального хранения их?только дисковое пространство?
Вас волнует, что адрес меняется (например, название улицы), но все еще адресует то же место?
Отслеживаете ли вы, если один из сотрудников переходит в квартиру, второй сотрудник уже живет?

нам не нужно вводить реальный мир в код, нам просто нужно исправить конкретные проблемы.На данный момент адрес в Вашей модели не зависит.Ваша система одинаково заботится о сотрудниках и адресах.это добавляет дополнительную сложность (см. GetExistingOrCreateNewAddress).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...