Я получаю сообщение об ошибке
Не удалось подключить объект типа «Application.Models.DatabaseModels.Bar», поскольку другой объект того же типа уже имеет такое же значение первичного ключа.
Я видел эту ошибку раньше и знаю, что она возникает, потому что я пытаюсь установить состояние экземпляра Bar
в измененное состояние, когда контекст уже отслеживает экземпляр с таким же идентификатором. Что меня интересует, так это ситуация, в результате которой Bar
отслеживается, прежде чем я пытаюсь установить состояние.
Ниже приведены два блока кода, которые идентичны во всех отношениях, за исключением добавления одной строки во втором блоке. Первая функция будет работать правильно, изменяя состояние foo.PrimaryBar
на измененное, тогда как вторая функция выдаст ошибку.
Это прекрасно работает:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(ViewModel viewModel)
{
Foo foo = await _context.Foos.AsNoTracking().FirstOrDefaultAsync(f => f.Id == viewModel.FooId);
Foo.Primary.Bar = _context.Bars.AsNoTracking().First(c => c.Id == viewModel.PrimaryBarId);
_context.SetModified(foo.Primary);
//code continues
}
Это выдает ошибку:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(ViewModel viewModel)
{
Foo foo = await _context.Foos.AsNoTracking().FirstOrDefaultAsync(f => f.Id == viewModel.FooId);
Foo.Primary.Bar = _context.Bars.AsNoTracking().First(c => c.Id == viewModel.PrimaryBarId);
//this appears to add the Bars in Foo to the context
var test = foo.Bars.Where(c => c.Id != foo.Primary.Bar.Id);
//this is where the error occurs now
_context.SetModified(foo.Primary);
//code continues
}
Чтобы дать контекст ситуации:
Модели баз данных
public class Foo
{
public int Id { get; set; }
[ForeignKey("Primary")]
public int? PrimaryId { get; set; }
public virtual Primary Primary { get; set; }
public virtual List<Bar> Bars { get; set; }
}
public class Bar
{
public int Id { get; set; }
[ForeignKey("Foo")]
public int? FooId { get; set; }
public virtual Foo Foo { get; set; }
}
public class Primary
{
[Key, ForeignKey("Foo")]
public int FooId { get; set; }
public virtual Foo Foo { get; set; }
[ForeignKey("Bar")]
public int? BarId { get; set; }
public virtual Bar Bar { get; set; }
}
Просмотр модели
public class ViewModel
{
public int FooId { get; set; }
public int? PrimaryBarId { get; set; }
}
Context
public class AppDbContext : DbContext
{
public virtual DbSet<Foo> Foos { get; set; }
public virtual DbSet<Bar> Bars { get; set; }
public virtual DbSet<Primary> PrimaryBars { get; set; }
public virtual void SetModified<T>(T entity) where T : class
{
Entry(entity).State = EntityState.Modified;
}
}
Вопрос
Почему строка var test = foo.Bars.Where(c => c.Id != foo.Primary.Bar.Id);
вызывает отслеживание Bar
контекста, даже если для foo
установлено значение AsNoTracking()
?
Я неправильно понимаю, что здесь происходит, что делает AsNoTracking()
, или это ошибка в самой Entity Framework?