Entity Framework Code First-метод No Detach() в DbContext


Мне интересно, почему нет метода отсоединения на объекте DbContext, как есть для ObjectContext.  Я могу только предположить, что это упущение было преднамеренным, но мне трудно понять, почему.  Мне нужно иметь возможность отсоединять и повторно присоединять объекты (для размещения в кэше в ASP.NET проект, например).  Однако, поскольку я не могу отсоединить сущность, когда я пытаюсь присоединить сущность, которая была связана с предыдущим контекстом, я получаю "объект сущности не может ссылаться на несколько экземпляров IEntityChangeTracker" исключение.

что здесь за руководство?  Я что-то упустил?

4 63

4 ответа:

для людей, которые могут наткнуться на этот вопрос, начиная с CTP5 вам теперь нужно написать

((IObjectContextAdapter)context).ObjectContext

для того, чтобы добраться до ObjectContext.

DbContext использует ObjectContext внутренне и команда EF делает это доступным как защищенный свойство на всякий случай, если вам когда-нибудь понадобится перейти к API более низкого уровня и звучит так, как здесь, поэтому вы можете использовать или предоставлять необходимые функции из производного DbContext:

public class YourContext : DbContext 
{
    public void Detach(object entity) 
    {
        ObjectContext.Detach(entity);            
    }
}

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

кроме того, вы можете изменить его, чтобы даже богаче API:

public class YourContext : DbContext
{
    public void ChangeObjectState(object entity, EntityState entityState)
    {
        ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState);
    }
}

вот как выглядит DbContext из метаданных:

public class DbContext : IDisposable 
{      
    protected System.Data.Objects.ObjectContext ObjectContext { get; }
    ...
}

EF: CF 4.1 RC1 и EF:CF 4.1 RTW имеют тот же явно реализованный IObjectContextAdapter:

public static class DbContextExtensions
{
    public static void Detach(this System.Data.Entity.DbContext context, object entity)
    {
         ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity);
    }
}

Microsoft решила "отсоединить слишком передовые технологии и должны быть скрыты". IMHO человек, который изобрел это, должен быть застрелен - потому что если вы добавляете совершенно новую сущность, в противном случае трудно просто удалить ее, не совершая изменений в db (вы можете манипулировать DbEntityEntry, но это другая история).

редактировать 4 года позже:

С ef6 в (Я как-то пропустил EF5 :) ) вам не нужно detach() больше, потому что удаление недавно добавленной записи не генерирует delete from [table] where [Id] = 0 как в EF4 - вы можете просто позвонить mySet.Remove(myFreshlyCreatedAndAddedEntity) и все будет хорошо.

Я обычно расширяю базовый класс (наследует от DbContext) со свойством:

public class MyDbContext : DbContext
{
    public ObjectContext ThisObjectContext
    {
        get
        {
            return ((IObjectContextAdapter)this).ObjectContext;
        }
    }
}

позже вы можете использовать это свойство для различных полезных вещей ... как отсоединить :)