Объект сущности не может ссылаться на несколько экземпляров IEntityChangeTracker. ' [Дубликат]

[Д0] 1. Обозначение фрагмента

Чтобы сделать его простым, помните, что фрагмент имеет только одну форму:

s[start:end:step]

и вот как это работает:

  • s: объект, который можно нарезать
  • start: первый индекс для начала итерации
  • end: последний индекс, ПРИМЕЧАНИЕ, что индекс end не будет включен в приведенный срез
  • step: выбрать элемент каждый step индекс

Еще одна вещь для импорта: все start, end, step могут быть опущены ! И если они опущены, их значение по умолчанию будет использовано: 0, len(s), 1 соответственно.

Возможны следующие варианты:

# mostly used variations
s[start:end]
s[start:]
s[:end]

# step related variations
s[:end:step]
s[start::step]
s[::step]

# make a copy
s[:]

ПРИМЕЧАНИЕ: Если start>=end (учитывая только когда step>0), python вернет пустой срез [].

2. Pitfalls

В приведенной выше части объясняются основные функции работы среза, они будут работать в большинстве случаев. Тем не менее, могут возникнуть ошибки, о которых вы должны помнить, и эта часть объясняет их.

Отрицательные индексы

Самое первое, что смущает учеников python, - это то, что индекс может быть отрицательным! Не паникуйте: отрицательный индекс означает подсчет с обратной стороны.

Например:

s[-5:]    # start at the 5th index from the end of array, 
          # thus returns the last 5 elements
s[:-5]    # start at index 0, end until the 5th index from end of array, 
          # thus returns s[0:len(s)-5]

Отрицательный шаг

Сделать вещи более запутанными в том, что step также может быть отрицательным!

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

ПРИМЕЧАНИЕ: когда шаг отрицательный, значение по умолчанию для start - len(s)end не равно 0, потому что s[::-1] содержит s[0]). Например:

s[::-1]            # reversed slice
s[len(s)::-1]      # same as above, reversed slice
s[0:len(s):-1]     # empty list

Ошибка вне диапазона?

Будьте удивлены: срез не увеличивает индекс IndexError, когда индекс выходит за пределы диапазона!

Если индекс находится за пределами допустимого диапазона, python попытается наилучшим образом настроить индекс на 0 или len(s) в соответствии с ситуацией. Например:

s[:len(s)+5]      # same as s[:len(s)]
s[-len(s)-5::]    # same as s[0:]
s[len(s)+5::-1]   # same as s[len(s)::-1], same as s[::-1]

3. Примеры

. Закончим этот ответ примерами, объясняющими все, что мы обсуждали:

# create our array for demonstration
In [1]: s = [i for i in range(10)]

In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [3]: s[2:]   # from index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]

In [4]: s[:8]   # from index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]

In [5]: s[4:7]  # from index 4(included) up to index 7(excluded)
Out[5]: [4, 5, 6]

In [6]: s[:-2]  # up to second last index(negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]

In [7]: s[-2:]  # from second last index(negative index)
Out[7]: [8, 9]

In [8]: s[::-1] # from last to first in reverse order(negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

In [9]: s[::-2] # all odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]

In [11]: s[-2::-2] # all even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]

In [12]: s[3:15]   # end is out of range, python will set it to len(s)
Out[12]: [3, 4, 5, 6, 7, 8, 9]

In [14]: s[5:1]    # start > end, return empty list
Out[14]: []

In [15]: s[11]     # access index 11(greater than len(s)) will raise IndexError
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]

IndexError: list index out of range
142
задан wonea 9 July 2012 в 18:04
поделиться

9 ответов

Поскольку эти две строки ...

EmployeeService es = new EmployeeService();
CityService cs = new CityService();

... не принимают параметр в конструкторе, я предполагаю, что вы создаете контекст внутри классов. Когда вы загружаете city1 ...

Payroll.Entities.City city1 = cs.SelectCity(...);

... вы присоединяете city1 к контексту в CityService. Позже вы добавите city1 в качестве ссылки на новый Employee e1 и добавьте e1 , включая эту ссылку, на city1 в контекст в EmployeeService. В результате у вас есть city1, прикрепленный к двум различным контекстам, о которых жалуется исключение.

Вы можете исправить это, создав контекст вне классов обслуживания и введя его и используя его в обеих службах:

EmployeeService es = new EmployeeService(context);
CityService cs = new CityService(context); // same context instance

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

Вы также можете создать единую службу, которая отвечает за набор тесно связанных объектов , как EmployeeCityService (который имеет один контекст) и делегирует всю операцию в вашем методе Button1_Click методу этой службы.

218
ответ дан Slauma 27 August 2018 в 10:42
поделиться

Это старый поток, но другое решение, которое я предпочитаю, просто обновляет cityId и не назначает модель дыры City to Employee ... для этого Employee должен выглядеть так:

public class Employee{
...
public int? CityId; //The ? is for allow City nullable
public virtual City City;
}

Тогда достаточно присвоить:

e1.CityId=city1.ID;
7
ответ дан halfer 27 August 2018 в 10:42
поделиться

В моем случае я использовал ASP.NET Identity Framework. Я использовал встроенный метод UserManager.FindByNameAsync для извлечения объекта ApplicationUser. Затем я попытался ссылаться на этот объект на вновь созданном объекте на другом DbContext. Это привело к исключению, которое вы изначально видели.

Я решил это, создав новый объект ApplicationUser только с Id из метода UserManager и ссылаясь на этот новый объект.

3
ответ дан Justin Skiles 27 August 2018 в 10:42
поделиться

У меня была та же проблема, и я мог решить создать новый экземпляр объекта, который я пытался обновить. Затем я передал этот объект в свой репозиторий.

1
ответ дан karolanet333 27 August 2018 в 10:42
поделиться

У меня была такая же проблема, но моя проблема с решением @ Slauma (хотя и велика в некоторых случаях) заключается в том, что она рекомендует передать контекст в службу, что подразумевает, что контекст доступен из моего контроллера. Это также создает плотную связь между моим контроллером и сервисными слоями.

Я использую Injection Dependency для ввода слоев сервиса / репозитория в контроллер и, как таковой, не имеет доступа к контексту с контроллера.

Мое решение состояло в том, чтобы слои службы / репозитория использовали один и тот же экземпляр контекста - Singleton.

Контекст Singleton Class:

Ссылка: http://msdn.microsoft.com/en-us/library/ff650316.aspx и http://csharpindepth.com/Articles/General/Singleton.aspx

public sealed class MyModelDbContextSingleton
{
  private static readonly MyModelDbContext instance = new MyModelDbContext();

  static MyModelDbContextSingleton() { }

  private MyModelDbContextSingleton() { }

  public static MyModelDbContext Instance
  {
    get
    {
      return instance;
    }
  }
}  

Класс репозитория:

public class ProjectRepository : IProjectRepository
{
  MyModelDbContext context = MyModelDbContextSingleton.Instance;

Существуют другие решения, такие как создание экземпляра контекст один раз и передать его в конструкторы слоев службы / репозитория или другое, о котором я читал, в котором реализуется шаблон «Единица работы». Я уверен, что есть еще ...

4
ответ дан kmullings 27 August 2018 в 10:42
поделиться

Источник ошибки:

ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.Name);
ApplicationDbContext db = new ApplicationDbContent();
db.Users.Uploads.Add(new MyUpload{FileName="newfile.png"});
await db.SavechangesAsync();/ZZZZZZZ

Надеюсь, кто-то сэкономит драгоценное время

-2
ответ дан MikeTheLiar 27 August 2018 в 10:42
поделиться

Использовать один и тот же объект DBContext во всей транзакции.

0
ответ дан Nalan Madheswaran 27 August 2018 в 10:42
поделиться

Шаги для воспроизведения можно упростить:

var contextOne = new EntityContext();
var contextTwo = new EntityContext();

var user = contexOne.Users.FirstOrDefault();

var group = new Group();
group.User = user;

contextTwo.Groups.Add(group);
contextTwo.SaveChanges();

Код без ошибок:

var context = new EntityContext();

var user = context.Users.FirstOrDefault();

var group = new Group();
group.User = user; // Be careful when you set entity properties. 
// Be sure that all objects came from the same context

context.Groups.Add(group);
context.SaveChanges();
19
ответ дан Pavel Shkleinik 27 August 2018 в 10:42
поделиться

В качестве альтернативы инъекции и еще хуже Singleton вы можете вызвать метод Detach до добавления.

EntityFramework 6: ((IObjectContextAdapter)cs).ObjectContext.Detach(city1);

EntityFramework 4: cs.Detach(city1);

Существует еще один способ, если вам не нужен первый объект DBContext. Просто оберните его с помощью ключевого слова:

Payroll.Entities.City city1;
using (CityService cs = new CityService())
{
  city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));
}
4
ответ дан Roman O 27 August 2018 в 10:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: