Эта проблема имеет две типичные причины:
Если объекты в вашем списке хранят данные в статических полях, каждый объект в вашем списке будет казаться одним и тем же, поскольку они удерживают одинаковые значения. Рассмотрим следующий класс:
public class Foo {
private static int value;
// ^^^^^^------------ - Here's the problem!
public Foo(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
В этом примере есть только один int value
, который разделяется между всеми экземплярами Foo
, поскольку он объявлен static
. (См. учебник «Знакомство с членами класса» .)
Если вы добавите несколько объектов Foo
в список, используя приведенный ниже код, каждый экземпляр вернет 3
из вызова to getValue()
:
for (int i = 0; i < 4; i++) {
list.add(new Foo(i));
}
Решение прост - не используйте ключевые слова static
для полей вашего класса, если вы действительно не хотите, чтобы значения были разделены между каждым экземпляром этого класса.
Если вы добавите временную переменную в список, вы должны создать новый экземпляр каждый раз, когда вы выполняете цикл. Рассмотрим следующий ошибочный фрагмент кода:
List list = new ArrayList();
Foo tmp = new Foo();
for (int i = 0; i < 3; i++) {
tmp.setValue(i);
list.add(tmp);
}
Здесь объект tmp
был создан вне цикла. В результате один экземпляр объекта добавляется в список три раза. Экземпляр будет содержать значение 2
, потому что это значение было передано во время последнего вызова setValue()
.
Чтобы исправить это, просто переместите конструкцию объекта внутри цикла:
List list = new ArrayList();
for (int i = 0; i < 3; i++) {
Foo tmp = new Foo(); // <-- fresh instance!
tmp.setValue(i);
list.add(tmp);
}
Вы вообще не используете new NavigationContext(...)
, вы полностью упускаете точку внедрения зависимости, если делаете это. Вместо этого вы должны внедрить контекст в класс, который в этом нуждается. Например, если вам нужно это прямо в вашем контроллере, это будет выглядеть примерно так:
public class FunkyController : Controller
{
private readonly NavigationContext _nagivationContext;
public FunkyController(NagivationContext nagivationContext)
{
//Context is injected into the constructor of the controller
_nagivationContext = nagivationContext;
}
public int Add(TEntity item)
{
_nagivationContext.Set<TEntity>().Add(item);
_nagivationContext.SaveChanges();
return item.Id;
}
}
Это не так, как вы делаете DI (Dependency Injection). Всякий раз, когда вы видите ключевое слово new
для службы, вы должны знать, что это неправильно.
Во-первых, вам не нужно ничего передавать в DbContext, этого переопределения OnConfiguring
не должно быть, поскольку вы его не используете. Этот вызов заботится об этой конфигурации:
services.AddDbContext<NavigationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("NavigationLoggingDatabase")));
Во-вторых, вы не используете using
с внедренными зависимостями, поэтому:
public int Add(TEntity item)
{
_context.Set<TEntity>().Add(item);
_context.SaveChanges();
return item.Id;
}
И, чтобы это работало: [ 1110]
public class SomeController : Controller
{
private readonly NavigationContext _context;
public SomeController(NagivationContext context)
{
_context = context;
}
}
И, как последний совет, вы должны действительно, действительно, максимально использовать асинхронные версии методов Entity Framework Core:
public async Task<int> Add(TEntity item)
{
_context.Set<TEntity>().Add(item);
await _context.SaveChangesAsync();
return item.Id;
}