Руководство по синхронизации обратных связей в Entity Framework 4.1 - PullRequest
8 голосов
/ 06 июня 2011

EF 4.1 синхронизирует обратные ассоциации при создании ваших экземпляров.Существует ли какая-либо документация или руководство по передовому опыту для этого поведения?

Что я имею в виду под синхронизацией обратной связи, это то, что дано:

public class Blog
{
   public Blog() { Posts = new List<Blog>(); }
   public int Id { get; set; }
   public ICollection<Post> Posts { get; private set; }
}

public class Post
{
   public Blog Blog { get; set; }
   public int Id { get; set; }
}

Затем после следующей строки сообщение будет иметьэто набор свойств блога.

var blog = new Blog();
context.Blogs.Add(blog);
blog.Posts.Add(new Post());

1 Ответ

9 голосов
/ 07 июня 2011

Я верю - но я не уверен - под «синхронизацией обратной связи» вы подразумеваете функцию в Entity Framework, которая называется Исправление отношений или Диапазон отношений и отвечает за автоматическое назначение свойств навигации между объектами в ObjectContext. Это не относится к EF 4.1, но существует и для более старых версий.

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

Редактировать

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

В ответе , который вы связали в комментарии Мортеза делает различие между сущностями, полученными из EntityObject (только ObjectContext в EF 4.0, невозможно с DbContext в EF 4.1) и POCO (возможно с ObjectContext и DbContext).

Если у вас есть POCO, то добавление нового объекта в коллекцию навигации другого объекта, который уже загружен в контекст, не присоединяет новый объект к контексту. Это неудивительно, потому что POCO - это, ну ... POCO, что означает, что они ничего не знают о контексте EF. Добавление объекта в коллекцию навигации - это не что иное, как List<T>.Add(...). Этот универсальный Add метод не выполняет никаких операций в контексте EF.

Это другая ситуация с EntityObject и EntityCollection, которые оба имеют внутренние ссылки на контекст и, следовательно, могут присоединяться к контексту сразу при добавлении в коллекцию.

Одним из выводов из этого соображения является то, что последний пример кода в вашем вопросе не фактически устанавливает свойство Blog в Post при использовании POCO. Но: будет установлен после того, как вы позвоните DetectChanges или SaveChanges (что вызывает DetectChanges внутри страны). В этой ситуации DetectChanges (что, вероятно, очень сложный метод) изучает контекст, какие объекты есть (он найдет родительский объект Blog), а затем пробегает весь граф объектов (коллекция Posts в нашем case) и проверяет, находятся ли другие объекты в графе (объекты Post) также в контексте. Если нет - и это имеет место в вашем примере - он присоединит их к контексту в состоянии Added и - в этом случае диапазон отношений в игру сейчас - также исправит свойства навигации в графе объектов.

Другая ситуация, когда диапазон отношений также действует с POCO, - это когда вы загружаете объекты в контекст.

Например: если у вас есть Blog с id = x и Post с id = y, который принадлежит этому Blog в базе данных, тогда этот код ...

var blog = context.Blogs.Find(x); // no eager loading of the Posts collection!
var post = context.Posts.Find(y); // no eager loading of the Blog property!

автоматически создает свойства навигации в каждом объекте, поэтому коллекция Posts Blog внезапно будет содержать сообщение, а свойство Blog в Post будет ссылаться на блог. Это исправление отношений зависит от того факта, что объекты действительно загружаются в контекст. Если вы подавите это, используя AsNoTracking, например ...

var blog = context.Blogs.AsNoTracking().Where(b => b.Id == x).Single();
var post = context.Posts.AsNoTracking().Where(p => p.Id == y).Single();

... диапазон отношений не работает, а свойства навигации останутся null.

Последнее примечание: диапазон отношений - как в примере выше - работает только в том случае, если для связи по крайней мере на одном конце количество элементов составляет 0...1 (связи один-к-одному или один-ко-многим). Это никогда не работает для многих ко многим ассоциациям. Это недавно обсуждалось здесь (с EF 4.1): EF 4.1 загрузка отфильтрованных дочерних коллекций не работает для многих ко многим

...