Wie schreibt man einen Entitätsvergleicher in C # (mit Beispielcode für den ersten Versuch)

.net c# comparison entity-framework performance

Frage

Mögliches Duplizieren:
Wie lassen sich zwei Entity Framework Entities am besten vergleichen?

Ich möchte die effizienteste Methode zum Vergleich zweier Entitäten desselben Typs kennen.

Eine Entität wird von Hand aus einer XML-Datei erstellt (dh neue Instanz und manuell gesetzte Eigenschaften), und die andere Entität wird aus meinem Objektkontext übernommen.

Ich möchte wissen, ob die Eigenschaftswerte in jeder Instanz gleich sind.

Meine ersten Gedanken sind, einen Hash der Eigenschaftswerte von jedem Objekt zu generieren und die Hashes zu vergleichen, aber es könnte einen anderen Weg geben oder einen eingebauten Weg?

Anregungen wären willkommen.

Danke vielmals,

James

AKTUALISIEREN

Ich kam dazu:

static class ObjectComparator<T>
{
    static bool CompareProperties(T newObject, T oldObject)
    {
        if (newObject.GetType().GetProperties().Length != oldObject.GetType().GetProperties().Length)
        {
            return false;
        }
        else
        {
            var oldProperties = oldObject.GetType().GetProperties();

            foreach (PropertyInfo newProperty in newObject.GetType().GetProperties())
            {
                try
                {
                    PropertyInfo oldProperty = oldProperties.Single<PropertyInfo>(pi => pi.Name == newProperty.Name);

                    if (newProperty.GetValue(newObject, null) != oldProperty.GetValue(oldObject, null))
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }
            }

            return true;
        }
    }
}

Ich habe es noch nicht getestet, es ist eher ein Denkanstoß, um weitere Ideen aus der Gruppe zu generieren.

Ein Problem, das möglicherweise ein Problem darstellt, ist das Vergleichen von Eigenschaften, die selbst über Entitätswerte verfügen. Wenn der Standardvergleicher die Objektreferenz vergleicht, ist er niemals wahr. Eine mögliche Lösung besteht darin, den Gleichheitsoperator meiner Entitäten zu überladen, damit er die Entitäts-ID vergleicht.

Akzeptierte Antwort

So wird der Code nicht das tun, was Sie erwarten.

Versuchen Sie diesen einfachen Test:


class A {
    public int Id { get; set; }
    public string Name { get; set; }
}

class B : A {
    public DateTime BirthDate { get; set; }
}

class ObjectComparer {
    public static void Show() {
        A a = new A();
        B b = new B();
        A a1 = new A();

        Console.WriteLine(ObjectComparator.CompareProperties(a, b));
        Console.WriteLine(ObjectComparator.CompareProperties(b, a));
        Console.WriteLine(ObjectComparator.CompareProperties(a, a1));
    }
}

Sie würden erwarten, dass es wiederkommt

falsch

falsch

wahr

aber es kehrt zurück

falsch

falsch

falsch

Versuchen Sie, das Innere zu ändern, wenn Sie wie folgt aussehen:


if (!object.Equals(newProperty.GetValue(newObject, null), oldProperty.GetValue(oldObject, null))) { 
       return false; 
} 

Sie können auch etwas Zeit sparen, wenn a und a1 beide auf dasselbe Objekt verweisen, indem Sie dies am Anfang der Methode überprüfen.


static class ObjectComparator { 
    public static bool CompareProperties(T newObject, T oldObject) {
        if (object.Equals(newObject, oldObject)) {
            return true;
        }
        if (newObject.GetType().GetProperties().Length != oldObject.GetType().GetProperties().Length) { 
            return false; 
        } 
        else { 
            var oldProperties = oldObject.GetType().GetProperties(); 
            foreach (PropertyInfo newProperty in newObject.GetType().GetProperties()) { 
                try { 
                    PropertyInfo oldProperty = oldProperties.Single(pi => pi.Name == newProperty.Name); 
                    if (!object.Equals(newProperty.GetValue(newObject, null), oldProperty.GetValue(oldObject, null))) { 
                        return false; 
                    } 
                } 
                catch { 
                    return false; 
                } 
            } 
            return true; 
        } 
    } 
}

Wenn Sie mit der Leistung konfrontiert sind, können Sie die Rückgabe von Type.GetProperties während der Laufzeit der Methode in eine lokale Variable zwischenspeichern, da Reflection dies bis mindestens Version 3.5 SP1 nicht selbst tut. In diesem Fall werden Sie GetProperties-Anrufe von vier auf zwei ablegen.

Wenn Sie nur den Vergleich von Objekten desselben Typs erwarten (oder eine andere Methode als den Vergleich zwischen Basis- und abgeleiteten Instanzen verwenden), können Sie die Aufrufe von GetProperties auf einen einzigen Aufruf reduzieren.

Hoffe das hilft.


Beliebte Antwort

Ich würde so etwas tun

static class ObjectComparator<T>
{
    public static bool CompareProperties(T newObject, T oldObject)
    {
        if (Equals(newObject, oldObject))
        {
            return true;
        }
        PropertyInfo[] newProps = newObject.GetType().GetProperties();
        PropertyInfo[] oldProps = oldObject.GetType().GetProperties();

        if (newProps.Length != oldProps.Length)
        {
            return false;
        }

        foreach (PropertyInfo newProperty in newProps)
        {
            PropertyInfo oldProperty = oldProps.SingleOrDefault(pi => pi.Name == newProperty.Name);
            if (oldProperty == null)
                return false;

            object newval = newProperty.GetValue(newObject, null);
            object oldval = oldProperty.GetValue(oldObject, null);

            if (!Equals(newval, oldval))
                return false;
        }
        return true;
    }
}


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum