Frage

Ist es im Entity Framework möglich, dass das Framework den DBContext in jedes Objekt (Entität) injiziert oder aus dem Kontext abgerufen wird?

Ich bin ein Nhibernate -Typ und ich weiß, dass es in NH möglich ist, - Entschuldigung, wenn es eine dumme Frage in der EF -Welt ist.

Im Wesentlichen möchte ich, dass einige meiner Entitäten über eine Eigenschaft vom Typ dbContext verfügen, die durch das Framework selbst auf die Instanz des Kontexts festgelegt werden, wenn ich das Entität mit dem Kontext verbinde. Idealerweise werden solche Klassen mit der iContextaware -Marker -Schnittstelle oder ähnlichem gekennzeichnet.

Der Grund, warum ich dies tun möchte, ist (= Ziel), ich möchte diesmal ein Anämiedomänenmodell-Anti-Muster-Muster vermeiden. Ich dachte, wenn ich ObjectContext in Entitäten injiziert habe, können sie auf DB zugreifen, wodurch ich Abfragen und komplexere Logik direkt in Domänenklassen selbst implementieren kann. Wenn Sie andere Möglichkeiten kennen, um mein Ziel zu erreichen (insbesondere im Kontext der Web -App), tun Sie dies bitte, aber bitte versuchen Sie, Antworten wie "Sie sollten dies nicht tun" zu vermeiden. Vielen Dank!!!

War es hilfreich?

Lösung

Sie sollten dies nicht tun, weil Sie Beharrlichkeitsbedenken aus Ihren Domain -Objekten fernhalten möchten =)

Wenn Sie jedoch müssen, können Sie sich in das von ObjectContext abgefeuerte Objektmaterialienereignis einbinden. In CTP5 müssen Sie Ihren DBContext wie im Konstruktor für Ihren DBContext aufnehmen:

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

Implementieren Sie dann Ihre Funktion ObjectContext_onObjectMaterialized (Objektabsender, ObjectMaterializedEventArgs E). Über die EventArgs können Sie auf Ihr Objekt zugreifen, das gerade materialisiert wurde. Von dort aus können Sie die ObjectContext/DBContext -Eigenschaft Ihres PoCO festlegen, die entweder öffentlich oder intern sein muss.

Andere Tipps

Neben der Kopplung Ihrer Domäne an eine bestimmte Persistenance -Technologie gibt es andere Konstruktionen, die den Kontext auf dieser Ebene injizieren. Was ist beispielsweise die Lebensdauer des Kontextes, den Sie injizieren, und sollte dieser Kontext für jede Entität immer die gleiche Lebensdauer haben?

Ich verstehe, dass Sie Ihre Geschäftsmethoden in den Unternehmen definieren möchten, damit Sie sagen können customer.MakeCustomerPreferred. Es gibt jedoch andere Möglichkeiten, dies zu tun, ohne die Geschäftslogik auf dieser Ebene in der Anwendung schreiben zu müssen. Zum Beispiel können Sie Geschäftsereignisse nutzen. Hier ist ein Beispiel:

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; }
}

Das DomainEvents Klasse ist ein Umgebungskontext Dadurch können Sie alle Handler für das spezifische Domain -Ereignis erhalten und diese ausführen.

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);
        }
    }
}

Mit diesem vorhanden können Sie Ihre Handler in Ihrer Architektur auf einer höheren Ebene definieren und für jedes Geschäftsereignis Null, einen oder mehr Handler einfügen. Sie können den Kontext in einen Handler injizieren.

Wir bieten unseren Kunden die Möglichkeit, den vom Themenstarter angeforderten Ansatz zu befolgen. Dazu haben wir sogar eine ähnliche Lösung (die objektmaterialisierten und andere Ereignisse von ObjectContext und ObjectSemanager) in unserem ExpressApp -Framework (XAF) -Produkt implementiert. Dies funktioniert in den meisten Szenarien ohne Probleme, da Unternehmen die gleiche Lebenszeit wie der "Kontext" haben. Dies hilft uns auch, die Verwendbarkeit für unsere Kunden zu verbessern, die bei der Gestaltung ihrer Datenmodelle und der Geschäftslogik den gleichen Schwierigkeiten haben.

In unserem Fall ist das Domänenmodell nicht mit einer spezifischen Persistenztechnologie verbunden, da wir über eine spezielle "ObjectSpace" -Isfriktion im ORM -Kontext verfügen (zusätzlich zum Entitätsrahmen unterstützt unser Produkt unser internes ORM -Express -Persistenten (XPO )).

Wir bieten unseren Kunden also eine iObjectSpacelink -Schnittstelle (mit einer einzigen IObjectSpace -Eigenschaft) an, die von Unternehmen implementiert werden soll, die einen Kontext für ihre Geschäftslogik benötigen.

Darüber hinaus bieten wir eine ixafEntityObject -Schnittstelle (mit den On -Loaded -Onavet -Methoden) für die beliebtesten Geschäftsregeln. Hier ist ein Beispiel für ein Unternehmen, das beide Schnittstellen aus unserer BCL implementiert:

        // 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() {}

Hier ist hier der Code unseres Frameworks, der diese Teile intern verknüpft (unten für 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;
    }

Ich hoffe, diese Informationen helfen Ihnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top