Domanda

In Entity Framework, è possibile rendere il quadro iniettare il DbContext in ogni oggetto (entità) che è collegato o recuperato dal contesto?

Sono un ragazzo NHibernate e so che è possibile in NH, - scusate se è una domanda stupida nel mondo EF

.

In sostanza, voglio alcuni dei miei soggetti ad avere una proprietà di tipo DbContext che andranno impostato l'istanza del contesto da parte del framework stesso, ogni volta che mi associo l'entità con il contesto. Idealmente tali classi saranno contrassegnati con interfaccia marcatore IContextAware o qualcosa del genere.

Il motivo che voglio fare questo è (= obiettivo), voglio evitare Anemic Domain Model anti-modello questa volta. Ho pensato che se ho ObjectContext iniettato in entità, essi saranno in grado di accesso ai database, in tal modo che mi permette di implementare le query e logica più complessa classi di dominio proprio dentro se stessi. Se conoscete altri modi per raggiungere il mio obiettivo (esp. Nel contesto di web app) si prega di fare, ma per favore cercate di evitare risposte come "non si deve fare questo perché". Grazie !!!

È stato utile?

Soluzione

Non si dovrebbe fare questo perché si vuole mantenere la persistenza preoccupazioni sugli oggetti del dominio =)

Ma se è necessario, è possibile collegare in caso ObjectMaterialized licenziato da ObjectContext. In CTP5, è necessario lanciare la vostra DbContext in questo modo nel costruttore per la vostra DbContext:

((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += 
    this.ObjectContext_OnObjectMaterialized;

quindi implementare la funzione ObjectContext_OnObjectMaterialized (object sender, ObjectMaterializedEventArgs e). Via i EventArgs, si sarà in grado di accedere al tuo oggetto, che è stato appena materializzato. Da lì, è possibile impostare la vostra proprietà ObjectContext / DbContext di POCO, che deve essere pubblica o interna.

Altri suggerimenti

Oltre accoppiamento tuo dominio a una tecnologia specifica persistenza, ci sono altri conserns con l'iniezione del contesto a quel livello. Per esempio, qual è la durata del contesto iniettare e dovrebbe tale contesto hanno sempre la stessa durata per ogni entità?

ho capito che si desidera definire i metodi di business sulle entità, in modo da poter dire customer.MakeCustomerPreferred. Ci sono tuttavia altri modi per fare questo, senza dover scrivere la logica di business a quel livello nel relativa domanda. Per esempio, è possibile utilizzare eventi aziendali. Ecco un esempio:

public class Customer
{
    public void MakeCustomerPreferred()
    {
        var e = new MakeCustomerPreferredEvent()
        {
            Customer = this
        };

        DomainEvents.Current.Handle(e);
    }
}

public interface IDomainEvent { }

public interface IHandle<T> where T : IDomainEvent
{
    void Handle(T instance);
}

public class MakeCustomerPreferredEvent : IDomainEvent
{
    prop Customer Customer { get; set; }
}

La classe DomainEvents è un ambiente contesto che permette di ottenere tutti i gestori per l'evento dominio specifico e eseguirli.

public class DomainEvents
{
    public static DomainEvents Current = new DomainEvents();

    public virtual void Handle<T>(T instance) 
        where T : IDomainEvent
    {
        var handlers =
           YourIocContainer.GetAllInstances<IHandle<T>>();

        foreach (var handler in handlers)
        {
            handler.Handle(instance);
        }
    }
}

Con questo in luogo è possibile definire i gestori a un livello superiore nella vostra architettura e plug-in zero, uno o più gestori per ogni evento di business. È possibile iniettare il contesto in un gestore.

Forniamo ai nostri clienti con la possibilità di seguire l'approccio richiesto dal tema di avviamento. Per fare questo, abbiamo anche implementato una soluzione simile (l'ObjectMaterialized e altri eventi di ObjectContext e ObjectStateManager) nel nostro eXpressApp quadro (XAF) del prodotto. Questo funziona senza problemi nella maggior parte delle situazioni in quanto entità hanno lo stesso tempo di vita come il "contesto". Questo aiuta anche a migliorare l'usabilità per i nostri clienti che devono affrontare le stesse difficoltà nella progettazione dei loro modelli di dati e la logica di business.

Nel nostro caso, il modello di dominio non è accoppiato con una tecnologia specifica persistenza, perché abbiamo una speciale astrazione "ObjectSpace" sul contesto ORM (oltre a Entity Framework nostro prodotto supporta i nostri in-house ORM - eXpress persistente Objects (XPO)).

Così, offriamo ai nostri clienti un'interfaccia IObjectSpaceLink (con una singola proprietà IObjectSpace) che dovrebbe essere attuato da soggetti che richiedono il contesto per la loro logica di business.

Inoltre, mettiamo a disposizione un'interfaccia IXafEntityObject (con le OnCreated, OnLoaded, metodi OnSaving) per il maggior numero di regole di business popolari. Ecco un esempio di un'entità attuazione entrambe le interfacce del nostro BCL:

        // IObjectSpaceLink
    IObjectSpace IObjectSpaceLink.ObjectSpace {
        get { return objectSpace; }
        set { objectSpace = value; }
    }

    // IXafEntityObject
    void IXafEntityObject.OnCreated() {
        KpiInstance kpiInstance = (KpiInstance)objectSpace.CreateObject(typeof(KpiInstance));
        kpiInstance.KpiDefinition = this;
        KpiInstances.Add(kpiInstance);
        Range = DevExpress.ExpressApp.Kpi.DateRangeRepository.FindRange("Now");
        RangeToCompare = DevExpress.ExpressApp.Kpi.DateRangeRepository.FindRange("Now");
    }
    void IXafEntityObject.OnSaving() {}
    void IXafEntityObject.OnLoaded() {}

A sua volta, ecco il codice del nostro quadro che lega questi pezzi insieme internamente (sotto è per Entity Framework 6).

        private void ObjectContext_SavingChanges(Object sender, EventArgs e) {
        IList modifiedObjects = GetModifiedObjects();
        foreach(Object obj in modifiedObjects) {
            if(obj is IXafEntityObject) {
                ((IXafEntityObject)obj).OnSaving();
            }
        }
    }
    private void ObjectContext_ObjectMaterialized(Object sender, ObjectMaterializedEventArgs e) {
        if(e.Entity is IXafEntityObject) {
            ((IXafEntityObject)e.Entity).OnLoaded();
        }
    }
    private void ObjectStateManager_ObjectStateManagerChanged(Object sender, CollectionChangeEventArgs e) {
        if(e.Action == CollectionChangeAction.Add) {
            if(e.Element is INotifyPropertyChanged) {
                ((INotifyPropertyChanged)e.Element).PropertyChanged += new PropertyChangedEventHandler(Object_PropertyChanged);
            }
            if(e.Element is IObjectSpaceLink) {
                ((IObjectSpaceLink)e.Element).ObjectSpace = this;
            }
        }
        else if(e.Action == CollectionChangeAction.Remove) {
            if(e.Element is INotifyPropertyChanged) {
                ((INotifyPropertyChanged)e.Element).PropertyChanged -= new PropertyChangedEventHandler(Object_PropertyChanged);
            }
            if(e.Element is IObjectSpaceLink) {
                ((IObjectSpaceLink)e.Element).ObjectSpace = null;
            }
        }
        OnObjectStateManagerChanged(e);
    }
    public virtual Object CreateObject(Type type) {
        Guard.ArgumentNotNull(type, "type");
        CheckIsDisposed();
        Object obj = CreateObjectCore(type);
        if(obj is IXafEntityObject) {
            ((IXafEntityObject)obj).OnCreated();
        }
        SetModified(obj);
        return obj;
    }

Spero che queste informazioni ti aiuta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top