EFCodeFirst: связь между двумя объектами не может быть определена, потому что они прикреплены к разным объектам ObjectContext.

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

Коллекция элементов объекта рецепта показана ниже:

public virtual IList<Member> Members { get; set; }

а вот коллекция Recipes в сущности-члене:

public virtual IList<Recipe> Recipes { get; set; }

Я делаю следующее при создании своего DbContext, чтобы создать отношение «многие ко многим» в отдельной таблице.

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // have to specify these mappings using the EF Fluent API otherwise I end up with
        // the foreign key fields being placed inside the Recipe and Member tables, which wouldn't
        // give a many-to-many relationship
        modelBuilder.Entity<Recipe>()
            .HasMany(r => r.Members)
            .WithMany(m => m.Recipes)
        .Map(x => {
            x.ToTable("Cookbooks"); // using a mapping table for a many-to-many relationship
            x.MapLeftKey("RecipeId");
            x.MapRightKey("MemberId");
        });

        modelBuilder.Entity<Recipe>()
            .HasRequired(x => x.Author)
            .WithMany()
            .WillCascadeOnDelete(false);

    }

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

Это часть кода в моем действии контроллера рецептов, который выполняет эту работу:

var memberEntity = memberRepository.Find((int)memberId);
var recipeEntity = recipeRepository.Find(recipeId);
recipeEntity.Members.Add(memberEntity);
recipeRepository.InsertOrUpdate(recipeEntity);
recipeRepository.Save();

Вот метод вставки или обновления в моем репозитории рецептов

    public void InsertOrUpdate(Recipe recipe)
    {
        if (recipe.Id == default(int))
        {
            // New entity
            context.Recipes.Add(recipe);
        } else
        {
            // Existing entity
            context.Entry(recipe).State = EntityState.Modified;
        }
    }

Я получаю сообщение об ошибке «InvalidOperationException: связь между двумя объектами не может быть определена, потому что они прикреплены к разным объектам ObjectContext». в этой строке:

context.Entry(recipe).State = EntityState.Modified;

Кто-нибудь знает, почему это произошло? Должен ли я добавлять член в рецепт и наоборот, чтобы это работало? Я не уверен, в чем проблема, потому что recipeEntity кажется правильным.

Любая помощь будет оценена, спасибо.

ИЗМЕНИТЬ Контекст создается в каждом репозитории (RecipeRepository и MemberRepository), как показано, поэтому я предполагаю, что проблема заключается в том, что для каждого запроса .Find () используется другой контекст? и что вызывает проблемы?

private EatRateShareDbContext context = new EatRateShareDbContext();

person Pricey    schedule 05.09.2012    source источник
comment
Как вы создаете объект контекста? Есть ли у вас отдельный контекст EF для каждого репозитория?   -  person petro.sidlovskyy    schedule 06.09.2012
comment
Есть репозиторий? поделитесь кодом ..   -  person ashutosh raina    schedule 06.09.2012


Ответы (2)


Я не уверен, что это решение, но похоже, что вы используете разные контексты в своем репозитории.
Сначала убедитесь, что у вас одинаковый контекст для каждого времени жизни. Срок службы может отличаться в зависимости от типа вашего проекта. (например, для веб-проектов обычно одинаково для каждого HttpContext). Вы можете использовать IoC для управления временем жизни вашего контекста. Хорошими библиотеками IoC для .Net являются autofac и Виндзорский замок

Кроме того, я думаю, что ваш вызов метода InsertOrUpdate не нужен (если вы не вызываете метод Find без отслеживания.) Просто удалите строку и посмотрите, работает ли она:

var recipeEntity = recipeRepository.Find(recipeId);
recipeEntity.Members.Add(memberEntity);
recipeRepository.Save();

Один простой способ поделиться своим DbContext для HttpRequest упоминается здесь.

person Kamyar    schedule 05.09.2012
comment
В этом примере у меня есть 2 репозитория RecipeRepository и MemberRepository, каждый из которых передается в соответствующие конструкторы контроллеров с помощью Ninject DI. Каждое репо создает экземпляр моего DbContext, поэтому я предполагаю, что проблема связана с этим? и как вы упомянули разные времена жизни? Я рассмотрю также удаление вызова inserttorupdate, я не знал, что мне не нужно обновлять при изменении коллекции на подобном объекте. Спасибо - person Pricey; 06.09.2012
comment
да. Я думаю, что корень проблемы в другом DbContexts. У меня всегда один и тот же DbContext для каждого времени жизни HttpRequest. Пожалуйста, посмотрите мое обновление - person Kamyar; 06.09.2012

Если вы используете AutoFac, вы должны добавить SingleInstance () в свой регистрационный код.

Пример: builder.Register (a => new EntityContainer ()). As (). SingleInstance ()

Где EntityContainer - это ваш DbContext

person anonymous    schedule 15.03.2014