Использует ли LINQ to Entities экземпляры объектов повторно?
Вопрос
Использование LINQ to Entities кажется отличным способом выполнять запросы к базе данных и получать реальные объекты CLR, которые я могу изменять, привязывать данные и т. д.Но если я выполню тот же запрос во второй раз, получу ли я обратно ссылки на те же объекты CLR или совершенно новый набор?
Я не хочу, чтобы несколько запросов создавали постоянно растущее количество копий одних и тех же фактических данных.Проблема здесь в том, что я мог бы изменить содержимое одного объекта и сохранить его обратно в базу данных, но другой экземпляр объекта все еще существует где-то еще и хранит старые данные.
Решение
В рамках одного и того же DataContext я понимаю, что вы всегда будете получать одни и те же объекты - для запросов, которые возвращают полные объекты вместо проекций.
Различные DataContexts будут извлекать разные объекты, так что есть риск увидеть устаревшие данные, да.
Другие советы
В том же DataContext вы получите тот же объект, если он будет запрошен (DataContext поддерживает для этого внутренний кеш).
Имейте в виду, что объекты, с которыми вы работаете, скорее всего, изменчивы, поэтому вместо одной проблемы (дублирование данных) вы можете получить другую (одновременный доступ).
В зависимости от бизнес-ситуации может быть допустимо, чтобы вторая транзакция с устаревшими данными не выполнялась при фиксации.
Кроме того, представьте себе старый добрый сценарий IDataReader / DataSet. Два запроса вернут двух разных читателей, которые будут заполнять разные наборы данных. Таким образом, проблема дублирования данных не зависит от ORM.
[упс;обратите внимание, что этот ответ относится к Linq-to-SQL, а не к Entity Framework.]
Я оставил его здесь (а не удалил), потому что он частично соответствует теме и может быть полезен.
В дополнение к другим ответам обратите внимание, что контекст данных также имеет возможность избежать двустороннего обхода для простых запросов «по первичному ключу» - сначала он проверит кеш.
К сожалению, это было полностью сломался в 3.5 и до сих пор полусломанный в 3.5SP1, но работает для некоторый запросы.Это может сэкономить много времени, если вы получаете отдельные объекты.
Итак, в основном, IIRC вам нужно использовать:
// uses object identity cache (IIRC)
var obj = ctx.Single(x=>x.Id == id);
Но нет:
// causes round-trip (IIRC)
var obj = ctx.Where(x=>x.Id == id).Single();