Какой самый быстрый способ получить ссылку ObjectContext от объекта сущности?

Я создаю расширения для своих объектов EntityFramework, как описано в разделе Практическое руководство. Настройка сгенерированных объектов данных, но в некоторых из этих расширений мне нужно получить ObjectContext экземпляра для поиска некоторых других значений в модели. Я нашел Совет 24 - Как получить ObjectContext от Entity, но он был написан пару лет назад, на который есть ссылка в этом похожем вопросе SO, но я действительно надеюсь, что сейчас есть лучший ответ.

Конечно, это должно быть чем-то, что требуется достаточно часто, чтобы извлечение контекста объекта сущности из самой сущности должно поддерживаться официальным методом.

Заранее спасибо за любую более свежую информацию об этой реализации.

3 ответа

Есть другое решение, использующее связанные свойства.

Использование связанных свойств будет выглядеть следующим образом (предупреждение: непроверенный код):

public partial class Database1Entities
{
    private struct ObjectContextProperty { }

    partial void OnContextCreated()
    {
        this.ObjectMaterialized += (_, e) =>
        {
            e.Entity.GetConnectedProperty<Database1Entities, ObjectContextProperty>().Set(this);
        };
        this.ObjectStateManager.ObjectStateManagerChanged += (_, e) =>
        {
            if (e.Action == CollectionChangeAction.Add)
            {
                e.Element.GetConnectedProperty<Database1Entities, ObjectContextProperty>().Set(this);
            }
            else if (e.Action == CollectionChangeAction.Remove)
            {
                e.Element.GetConnectedProperty<Database1Entities, ObjectContextProperty>().Set(null);
            }
        };
    }

    /// <summary>
    /// Gets the object context for the entity. Returns <c>null</c> if the entity is detached.
    /// </summary>
    /// <param name="entity">The entity for which to return the object context.</param>
    public static Database1Entities FromEntity(EntityObject entity)
    {
        return entity.GetConnectedProperty<Database1Entities, ObjectContextProperty>().GetOrConnect(null);
    }
}

Тогда вы можете использовать Database1Entities.FromEntity получить контекст объекта от объекта сущности. Вы также можете определить фактическое свойство для объектов сущности, если хотите:

public partial class Table1
{
    /// <summary> 
    /// Gets the object context for this entity. Returns <c>null</c> if the entity is detached.
    /// </summary> 
    public Database1Entities ObjectContext { get { return Database1Entities.FromEntity(this); } }
}

В этом решении ObjectContext Свойство на объектах объекта является необязательным.

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

Сначала добавьте хуки к контексту вашего объекта:

public partial class Database1Entities
{
    partial void OnContextCreated()
    {
        this.ObjectMaterialized += (_, e) =>
        {
            try
            {
                dynamic entity = e.Entity;
                entity.ObjectContext = this;
            }
            catch (RuntimeBinderException)
            {
            }
        };
        this.ObjectStateManager.ObjectStateManagerChanged += (_, e) =>
        {
            if (e.Action == CollectionChangeAction.Add)
            {
                try
                {
                    dynamic entity = e.Element;
                    entity.ObjectContext = this;
                }
                catch (RuntimeBinderException)
                {
                }
            }
            else if (e.Action == CollectionChangeAction.Remove)
            {
                try
                {
                    dynamic entity = e.Element;
                    entity.ObjectContext = null;
                }
                catch (RuntimeBinderException)
                {
                }
            }
        };
    }
}

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

Затем добавьте ObjectContext к типам сущностей:

public partial class Table1
{
    /// <summary> 
    /// Gets or sets the context for this entity.
    /// This should not be set by end-user code; this property will be set
    /// automatically as entities are created or added,
    /// and will be set to <c>null</c> as entities are detached.
    /// </summary> 
    public Database1Entities ObjectContext { get; set; }
}

Это решение требует ObjectContext свойство, которое будет добавлено к каждому типу объекта.

Нет, такого метода не существует. Описанный обходной путь выглядит как единственный вариант, потому что объект является производным от EntityObject который определяется как:

[Serializable, DataContract(IsReference=true)]
public abstract class EntityObject : StructuralObject, IEntityWithKey,  
    IEntityWithChangeTracker, IEntityWithRelationships
{
    ...
}

Как я знаю только IEntityWithRelationships.RelationshipManager приводит к ObjectContext, Это не изменилось в EF 4.

Кроме того, на самом деле не часто происходит доступ к контексту от объекта. Я могу себе представить, что это может быть полезно в случае реализации Active Record Pattern поверх EF, но в этом случае вы, вероятно, также можете контролировать создание контекста внутри статического метода объекта, поэтому вы сможете установить его на юридическое лицо. В других случаях я бы сказал, что этого следует избегать как можно больше.

Другие вопросы по тегам