Entity Framework 5 - поиск центральной точки для выполнения пользовательского кода после того, как объект загружается из базы данных

Я использую Entity Framework 5 с использованием подхода Code First и используя конфигурацию Fluent API для Entity. Мой проект имеет один конкретный объект продукта, который получает половину своих данных из базы данных, а другую половину - из Контракта данных, полученного через WCF-клиент (его сторонняя система, используемая для управления инвентаризацией продукта). Контракт данных является членом класса Product Entity (свойство или метод, который я еще не решил).

Я предпочитаю не иметь никакой логики WCF-клиента внутри Entities. Я бы предпочел сохранить эту логику в коде репозитория (DbContext, DbSet и т.д.).

Итак, существует ли метод для привязки к Entity Framework (или перехвату) сразу после того, как объект продукта извлекается из базы данных? Я должен отметить, что Product Entity отображается как свойство навигации для других объектов. Если возможен захват или перехват, то это означает, что я могу получить Контракт данных из службы SOAP сразу же после того, как EF загрузила Product Entity из базы данных. Преимущество моего проекта в том, что код поиска клиента WCF не обязательно должен повторяться во всем приложении.

Одна из моих идей заключалась в том, чтобы реализовать IDbSet для Контракта данных, и IDbSet будет отвечать за его получение. И тогда каким-то образом обманите EF, чтобы думать о его навигационной собственности в Product Entity. Но я не был уверен, что базу данных DbSet можно смешивать с IDbSet без базы данных в одном и том же DbContext. А также другой вопрос - как бы EF знал, чтобы получить свойство навигации из имплантации IDbSet? Я предпочел бы знать, возможна ли эта идея, прежде чем инвестировать в нее время. Я также предпочел бы знать, с чего начать искать.

Обратите внимание, что я работаю с .NET более 10 лет, но этот материал EF5 по-прежнему относительно нов для меня.

Спасибо заранее.

-Sam

Ответ 1

Сегодня я нашел событие в Entity Framework, которое, похоже, является тем, что я ищу. Событие ObjectContext.ObjectMaterialized. По-видимому, DbContext реализует IObjectContextAdapter, который в свою очередь предоставляет ObjectContext. Оттуда я могу подписаться на событие ObjectMaterialized.

MSDN Читает: Возникает, когда новый объект сущности создается из данных в данных источник как часть операции запроса или загрузки.

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

// seperate assembly - does not use Domain.Repositories assembly
namespace Domain.Models
{
    // the data contract
    [DataContract]
    public class ProductInventoryState
    {
        [DataMember]
        public int StockStatus { get; set; }

        [DataMember]
        public IEnumerable<String> SerialNumbers { get; set; }

        // etc....
    }

    // the entity
    public class Product
    {
        public Guid Key { get; set; }
        public string ProductCode { get; set; }
        public ProductInventoryState InventoryState { get; set; }
        // etc....
    }
}

// seperate assembly - uses Domain.Models assembly
namespace Domain.Repositories
{
    public class MainRepository : DbContext
    {
        public MainRepository()
        {
            ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += ObjectContext_ObjectMaterialized;
        }

        protected void ObjectContext_ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
        {
            if (e.Entity == null)
                return;

            if (e.Entity is Product)
            {
                Product product = (Product)e.Entity;

                // retrieve ProductInventoryState from 3rd party SOAP API
                using (ThirdPartyInventorySystemClient client = new ThirdPartyInventorySystemClient())
                {
                    // use ProductCode to retrieve the data contract
                    product.InventoryState = client.GetInventoryState(product.ProductCode);
                }
            }
        }    
    }
}

Ответ 2

1.) Вы можете написать собственный поставщик EF (но это небольшая задача)

2.) Вы можете прикреплять элементы к контексту, но не сохранять их.

Объект entity.State может быть установлен как "Не изменен после присоединения". Вы также можете удалить такие записи из контекста перед сохранением изменений.

3) Вы можете написать репозиторий, который проверяет EF и Checks location 2 и объединяет результат.

В вопросе свойств навигации. Вам нужно будет указать их очень осторожно, чтобы избежать проблем. Не ленивый загружен или даже не смоделирован.

Я бы не попробовал и не смешивал их лично.
Вы можете сказать EF игнорировать некоторые свойства. Таким образом, у вас может быть оригинальный POCO Nice, но только моделируйте биты, которые находятся в БД.

Затем POCO будет собирать остальные.

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

удача