Какой самый быстрый способ получить ссылку 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, но в этом случае вы, вероятно, также можете контролировать создание контекста внутри статического метода объекта, поэтому вы сможете установить его на юридическое лицо. В других случаях я бы сказал, что этого следует избегать как можно больше.