Entity Framework и DbContext - отслеживание объектов - PullRequest
2 голосов
/ 18 августа 2011

Я немного запутался в использовании DbContext в Entity Framework. Вот сценарий, по которому я запутался.

  • Я использую запрос linq из dbcontext для получения данных. Что-то вроде:

    List<Transactions> transactions = DefaultContext.Transactions.ToList();
    
  • Затем я обновляю столбец в одной из транзакций, возвращенных в этом запросе, непосредственно в базе данных.

  • Тогда я снова звоню:

    List<Transactions> transactions = DefaultContext.Transactions.ToList();
    

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

foreach (DbEntityEntry<Transactions> item in DefaultContext.ChangeTracker.Entries<Transactions>())
{
    DefaultContext.Entry<Transactions>(item.Entity).Reload();
}

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

Ответы [ 3 ]

8 голосов
/ 18 августа 2011

Это нормально и в случае фиксированного поведения API DbContext, потому что по какой-то очень странной причине ни DbSet, ни DbQuery не выставляют свойство MergeOption. В случае API ObjectContext вы можете установить поведение с помощью MergeOption, выставленного на ObjectSet и ObjectQuery. Поэтому, если вы хотите обновить значения из базы данных (и потерять свои изменения), вы можете сделать:

ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
ObjectSet<Transactions> set = objectContext.CreateObjectSet<Transactions>();
set.MergeOption = MergeOption.OverwriteChanges;
List<Transactions> transactions = set.ToList();

Если вы просто хотите обновить транзакции, но не хотите потерять изменения, вы можете использовать MergeOption.PreserveChanges.

2 голосов
/ 18 августа 2011

Это зависит от MergeOption запроса DefaultContext.Transactions.Значение по умолчанию AppendOnly, не будет перезаписывать объекты уже в вашем контексте. Вы можете изменить это значение на OverwriteChanges, чтобы получить ожидаемое поведение.

0 голосов
/ 02 ноября 2017

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

Строка кода, подобная приведенной ниже, потерпит неудачу при попытке привести некоторые IQueryables к классу ObjectQuery (но преуспеть в других.)

var y = ((ObjectQuery)query).MergeOption = MergeOption.NoTracking;

Вместо этого я заменил это на использование AsNoTracking

query = query.AsNoTracking();

Возвращаясь к исходному вопросу, это потенциально будет похоже на приведенный ниже метод расширения в DBQuery, добавленный в System.Data.Entity

List<Transactions> transactions = DefaultContext.Transactions.AsNoTracking().ToList();

Полугодовая статья: https://msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx

...