Сначала код - как я могу сохранить ICollection, когда я не устанавливаю родительский объект в EntityState.Modified? - PullRequest
4 голосов
/ 05 июня 2011

Если у меня есть следующий класс:

public class Foo()
{
public int PropertyIWantUpdated {get; set;}
public int PropertyIDontWantUpdated (get; set}

public ICollection<Bar> Bars {get; set;}
}

При сохранении в мою базу данных вместо

context.Entry(thisFoo).State = EntityState.Modified;

я использую

context.Entry(thisFood).Property(tf => tf.PropertyIWantUpdated).IsModified = true;

какможно также сохранить изменения в барах?

1 Ответ

5 голосов
/ 05 июня 2011

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

Если вы пытаетесь обновить только Bar экземпляров и не изменили отношения (= вы не добавили новые Bar в Foo или не удалили Bar из Foo), вам просто нужно итерируйте Bars и установите их в состояние Modified.

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

В случае связывания внешнего ключа (Bar имеет свойство FK в качестве свойства = в Bar у вас есть что-то вроде FooId), вы следуете тому же подходу, что и в начале. Вы повторяете Bars и устанавливаете состояние на:

  • Modified, если существующий Bar был присвоен Foo
  • Added, если новый Bar был присвоен Foo

Есть одна большая проблема. Если вы удалили несколько экземпляров Bar из коллекции Bars, вы также должны присоединить их к контексту и соответственно установить их состояние:

  • Modified, если FK должен быть установлен в ноль
  • Deleted если Bar следует удалить

Это все только для отношений один-ко-многим.

Если вы думали, что предыдущий подход сложен, будьте готовы к тому, что в случае независимой ассоциации (Bar не имеет свойства FK - всегда имеет место для отношений многих ко многим), процесс еще хуже. Независимые ассоциации имеют свой собственный объект, отслеживающий состояние = установка состояния на Bar сущность не сохраняет новые отношения. Первая проблема заключается в том, что этот объект не доступен напрямую из API DbContext - необходимо преобразовать DbContext в ObjectContext и использовать ObjectStateManager, чтобы получить доступ к ObjectStateEntry, представляющему отношение. После этого вы должны правильно установить его состояние, которое не так просто, как кажется, потому что отношение не может быть в состоянии Modified - оно может быть только в Unchanged, Added или Deleted. Это означает, что если вы изменили отношение Бар от одного к другому Foo, вы должны сначала найти старое отношение и установить его как удаленное, а затем вы можете установить новое отношение как добавленное. Если у вас есть отношение «многие ко многим», и вы также хотите добавлять, удалять и обновлять связанные объекты (не только отношения), это может быть действительно «большим удовольствием» - особенно тот факт, что вы должны где-то хранить информацию, которая изменилась, чтобы быть возможность правильно установить все состояния.

Более подробное обсуждение этой проблемы (глобально в EF) - здесь - оно не связано с API DbContext, но поскольку новый API является просто оболочкой старого API ObjectContext, остаются те же проблемы.

Как вы думаете, это осуществимо? Я так не думаю. Из-за этого вы должны попытаться избежать этого. Есть несколько способов, как этого избежать:

  • Вносить изменения в прикрепленный граф объектов - это означает, что сначала вы прикрепите исходное состояние графа сущностей к контексту, а затем внесете все свои изменения.
  • Загрузить исходный граф объектов и вручную объединить все изменения из нового графика в загруженный (и прикрепленный).
  • В случае ObjectContext API вы можете использовать Само-отслеживающиеся объекты , которые могут отслеживать состояние и автоматически устанавливать все, что применяется к контексту. У них есть некоторые другие недостатки и ограничения (например, они не поддерживают отложенную загрузку), и они недоступны для DbContext API.
...