Entity Framework 4 объединяет данные с отслеживаемым объектом

Сначала я борюсь с кодом Entity Framework и объединяюсь. У меня есть контроллер MVC с общим репозиторием. Модель представления публикуется, и я конвертирую ее в тип, о котором знает EF.

    var converted = AutoMapper.Mapper.Map<RoutineViewModel, Routine>(result);
    _routineRepository.Update(converted);

В репозитории у меня есть:

/*   
            Routines.Attach(item);
            ChangeTracker.Entries<Routine>().Single(x => x.Entity.Id == item.Id).State = EntityState.Modified;*/
            var match = Routines.Single(x => x.Id == item.Id);
            var entity = Entry(match);

            entity.CurrentValues.SetValues(item);

Я закомментировал первый бит, потому что он выдавал ошибку о том, что объект уже отслеживается, хотя такая проверка:

if (ChangeTracker.Entries<Routine>().Count(x => x.Entity.Id == item.Id) != 0)

вернул ложь

Проблема, с которой я сталкиваюсь, заключается в том, что объект Routine имеет свойство ICollection Steps. Когда я устанавливаю значения отслеживаемого объекта в соответствии со значениями poco, изменения ICollection не распространяются вниз. Глядя на этот сайт, можно увидеть несколько неприятных рекурсивных вызовов. Это действительно так работает или я что-то упускаю?

Есть ли простой способ сказать, вот исходный объект (неотслеживаемый), скопировать все о нем в отслеживаемый объект?

Просто чтобы быть ясным, я не думаю, что сначала нужно получить объект и обновить его свойства вне репозитория. Похоже, что это не только заставляет вас передавать ваши модели данных через границы домена, но и похоже вместо эквивалентного SQL-оператора (обновить x, y, где id = 1), чтобы (вставить во временную таблицу, где id = 1, для охвата строка в таблице temp, обновить x..... теперь для каждой строки в таблице обновления таблицы x = tempx, где id = 1)

Изменить. Итак, проблема в том, что setValues ​​​​не является рекурсивным вызовом. Подпрограммный объект имеет 2 простых свойства (идентификатор и имя) и одно сложное (ICollection). Если входящий элемент имеет измененное имя и некоторые шаги, setValues ​​улавливает изменение имени, но не применяется к дочерним элементам. Есть ли другой способ сделать это? Мне кажется немного скрипучим, что я должен вручную свернуть эту функциональность


person Dylan    schedule 24.02.2012    source источник


Ответы (1)


Из того, что я могу сказать, вы создаете свою сущность, заполняете свойства, а затем прикрепляете ее к БД. Это немного неправильно с EF.

Если вы хотите прикрепить объект, который уже находится в БД, но не отслеживается, вы можете использовать присоединение, но только изменения, сделанные после вызова присоединения, записываются для фиксации в БД. Если вы хотите использовать присоединение, убедитесь, что вы внесли свои изменения после вызова этого метода.

Кроме того, EF позволяет вам прикреплять только объект, которого в данный момент нет в графе объектов. Поэтому, если вы попытаетесь прикрепить один и тот же объект дважды (или один с одним и тем же ключом), вам будет выдана ошибка, подобная той, которую вы видите.

person Not loved    schedule 24.02.2012
comment
Привет, Люк, спасибо за информацию, но мне не нужно извлекать объект из репозитория, изменять его, а затем фиксировать только потому, что это EF. Мое предположение заключалось в том, что SetValues ​​в основном будет выполнять рекурсивное сравнение всех свойств и назначать любые несоответствующие отслеживаемым объектам. Что касается закомментированного кода, который выдает ошибку, объект не прикреплен (см. вызов средства отслеживания изменений ниже основного блока кода) и ни одно из его дочерних свойств, поскольку объект был создан полностью с нуля, но ошибка все еще имеет место. - person Dylan; 24.02.2012
comment
Если вы создаете совершенно новые объекты, обычным методом является использование Routines.Add(myNewRoutine), присоединение предназначено для повторного присоединения объектов, которые уже существуют в БД, но еще не были загружены в граф объектов. - person Not loved; 25.02.2012
comment
Привет, Люк, я намеренно пропустил часть кода, но у меня есть метод вставки, который вызывает Routines.Add(item); без проблем. Это просто для решения сценария обновления - person Dylan; 25.02.2012