2014-10-17 8 views
9

Próbuję uzyskać listę zmian, które zostały wprowadzone do modelu pracownika (obiekt 1) przy użyciu modelu EmployeeHistory (obiekt 2). Zasadniczo istnieje jeden rekord pracownika, ale istnieje kilka rekordów EmployeeHistory. Za każdym razem, gdy coś zmieni się w Pracowniku, nowy rekord jest dodawany do tabeli EmployeeHistory, która zawiera dane Pracownika przed zmianą. Chcę porównać każdą z rekordów EmployeeHistory i zwrócić listę ciągów informujących o wprowadzonych zmianach. Aby uzyskać listę zmian, chcę przetestować listę rekordów EmployeeHistory i porównać każdy rekord EmployeeHistory z poprzednim rekordem EmployeeHistory. I ostatni rekord EmployeeHistory będzie musiał być porównany z bieżącym rekordem Employee (obiekt 1), który jest bardzo podobny do właściwości. Czy jest jakiś sposób, aby to zrobić bez szalonej ilości instrukcji IF porównujących dwie właściwości w każdym z rekordów?Uzyskiwanie różnicy między dwoma obiektami o tych samych właściwościach

Jest to rodzaj co szukam:

public List<string> GetEmployeeMasterHistory(Models.EmployeeMaster employee,IEnumerable<EmployeeMasterHistory> employeeHistoryCollection) 
{ 
     foreach (var historyRecord in employeeHistoryCollection) 
     { 
      //Compare historyRecord to EmployeeCollection[historyRecord.Index() - 1] 
     } 
     return null; 
} 

już mam metodę, która wykonuje całą kontrolę dla każdej właściwości, ale nie będzie o wiele więcej właściwości dodane w przyszłości i zmęczony koniecznością dodawania nowych instrukcji IF i nie wydaje się bardzo wydajny.

Oto co EmployeeMasterHistory Record wygląda następująco:

public partial class EmployeeMasterHistory 
    { 
     public Nullable<int> EmployeeNumber { get; set; } 
     public Nullable<int> CompanyNumber { get; set; } 
     public string UserName { get; set; } 
     public string Initials { get; set; } 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public string FullName { get; set; } 
     public Nullable<bool> StatusFlag { get; set; } 
     public Nullable<System.DateTime> StartDate { get; set; } 
     public Nullable<System.DateTime> TerminationDate { get; set; } 
     public string Branch { get; set; } 
     public Nullable<int> DepartmentNumber { get; set; } 
     public string Supervisor { get; set; } 
     public Nullable<int> Shift { get; set; } 
     public Nullable<int> UnionNo { get; set; } 
     public string G2ID { get; set; } 
     public Nullable<bool> EnterTimeFl { get; set; } 
     public string Phone { get; set; } 
     public string Extension { get; set; } 
     public string CellPhone { get; set; } 
     public string Email { get; set; } 
     public Nullable<int> PrimaryJobRole { get; set; } 
     public Nullable<int> JobLevel { get; set; } 
     public Nullable<int> JobGroup { get; set; } 
     public string JobTitle { get; set; } 
     public string EmployeeType { get; set; } 
     public string PayType { get; set; } 
     public Nullable<decimal> Rate { get; set; } 
     public Nullable<System.DateTime> LastReviewDate { get; set; } 
     public Nullable<System.DateTime> NextReviewDate { get; set; } 
     public Nullable<System.DateTime> LastPayChangeDate { get; set; } 
     public string EmergencyContact { get; set; } 
     public string EmergencyContactRelationship { get; set; } 
     public string EmergencyContactPhone { get; set; } 
     public Nullable<bool> CPComputer { get; set; } 
     public Nullable<bool> CPPhone { get; set; } 
     public Nullable<bool> CPCreditCard { get; set; } 
     public Nullable<bool> CPGasCard { get; set; } 
     public Nullable<bool> CPKeys { get; set; } 
     public Nullable<bool> CPSecurityCard { get; set; } 
     public Nullable<bool> CPVehicle { get; set; } 
     public Nullable<bool> CPTools { get; set; } 
     public Nullable<bool> CPUniform { get; set; } 
     public string ModBy { get; set; } 
     public Nullable<System.DateTime> ModDate { get; set; } 
     public int ID { get; set; } 
     public string SalesRep { get; set; } 
     public string MiddleName { get; set; } 
     public Nullable<int> ManagerEmpNo { get; set; } 
     public Nullable<bool> TempFl { get; set; } 
     public Nullable<bool> PEWFl { get; set; } 
     public Nullable<bool> PGTFl { get; set; } 
     public Nullable<bool> PMPFl { get; set; } 
     public Nullable<bool> PPGEFl { get; set; } 
     public Nullable<bool> PPGFl { get; set; } 
     public Nullable<bool> PRCFl { get; set; } 
     public Nullable<bool> PTCFl { get; set; } 
     public Nullable<bool> PPFl { get; set; } 
     public Nullable<bool> SWPFl { get; set; } 
     public Nullable<int> PrimaryDivision { get; set; } 
     public string TechGroupID { get; set; } 
     public string TechLevelID { get; set; } 
     public Nullable<bool> TechATD { get; set; } 
     public Nullable<int> ReviewPeriod { get; set; } 
     public Nullable<bool> CorpFl { get; set; } 
    } 

Z góry dziękuję!

+0

Brzmi jak zadanie do odbicia od czubka głowy. –

+0

Możesz użyć odbicia, aby zidentyfikować właściwości do porównania. Wtedy jest to tylko kwestia użycia pętli zamiast pisania nowej klauzuli if dla każdej właściwości. Jeśli chcesz porównać tylko niektóre właściwości, możesz zdefiniować niestandardowy atrybut, aby włączyć właściwości do porównania lub zrezygnować. –

+0

Zrobiłem trochę badań nad refleksją, ponieważ jestem dla niej nowy. Zamierzam spróbować stworzyć rozwiązanie wykorzystujące to. Dzięki chłopaki, to bardzo pomocne. – user3788671

Odpowiedz

15

Tutaj jest bardzo proste podejście za pomocą refleksji:

 var oOldRecord = new EmployeeMasterHistory(); 
     oOldRecord.EmployeeNumber = 1; 
     var oNewRecord = new EmployeeMasterHistory(); 
     oNewRecord.EmployeeNumber = 2; 
     oNewRecord.CompanyNumber = 3; 

     var oType = oOldRecord.GetType(); 

     foreach (var oProperty in oType.GetProperties()) 
     { 
      var oOldValue = oProperty.GetValue(oOldRecord, null); 
      var oNewValue = oProperty.GetValue(oNewRecord, null); 
      // this will handle the scenario where either value is null 
      if (!object.Equals(oOldValue, oNewValue)) 
      { 
       // Handle the display values when the underlying value is null 
       var sOldValue = oOldValue == null ? "null" : oOldValue.ToString(); 
       var sNewValue = oNewValue == null ? "null" : oNewValue.ToString(); 

       System.Diagnostics.Debug.WriteLine("Property " + oProperty.Name + " was: " + sOldValue + "; is: " + sNewValue); 
      } 
     } 

Wyjście z tego przykładu jest:

Property EmployeeNumber was: 1; is: 2 
Property CompanyNumber was: null; is: 3 

Prawdopodobnie wymaga czyszczenia, ale powinien zacząć grę w dół właściwą drogę.

+0

Może '! Object.Equals (oOldValue, oNewValue)'? – nrofis

+0

@nrofis: doskonała sugestia!Nadal trzeba radzić sobie z zerami podczas rejestrowania różnic, ale to powinno być nieco łatwiejsze w obsłudze. –

+0

Bardzo dziękuję – user3788671

10

Inna odpowiedź to dobry początek. Ale poszedłem naprzód i napisałem ten bardziej rozbudowany przykład, więc pomyślałem, że równie dobrze mogę to opublikować. Ten obsługuje wartości null i oferuje sposób rezygnacji z właściwości z porównania. Jest to nadal podstawowe, ale powinno cię to zabrać dalej, zakładając, że wspomniana wcześniej biblioteka nie jest tym, czego chcesz użyć.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 

namespace TestCompareProperties 
{ 
    class Program 
    { 
     class IgnorePropertyCompareAttribute : Attribute { } 

     class A 
     { 
      public int Property1 { get; private set; } 
      public string Property2 { get; private set; } 
      [IgnorePropertyCompare] 
      public bool Property3 { get; private set; } 

      public A(int property1, string property2, bool property3) 
      { 
       Property1 = property1; 
       Property2 = property2; 
       Property3 = property3; 
      } 
     } 

     class PropertyCompareResult 
     { 
      public string Name { get; private set; } 
      public object OldValue { get; private set; } 
      public object NewValue { get; private set; } 

      public PropertyCompareResult(string name, object oldValue, object newValue) 
      { 
       Name = name; 
       OldValue = oldValue; 
       NewValue = newValue; 
      } 
     } 

     private static List<PropertyCompareResult> Compare<T>(T oldObject, T newObject) 
     { 
      PropertyInfo[] properties = typeof(T).GetProperties(); 
      List<PropertyCompareResult> result = new List<PropertyCompareResult>(); 

      foreach (PropertyInfo pi in properties) 
      { 
       if (pi.CustomAttributes.Any(ca => ca.AttributeType == typeof(IgnorePropertyCompareAttribute))) 
       { 
        continue; 
       } 

       object oldValue = pi.GetValue(oldObject), newValue = pi.GetValue(newObject); 

       if (!object.Equals(oldValue, newValue)) 
       { 
        result.Add(new PropertyCompareResult(pi.Name, oldValue, newValue)); 
       } 
      } 

      return result; 
     } 

     static void Main(string[] args) 
     { 
      A[] rga = { new A(1, "1", false), new A(2, "1", true), new A(2, null, false) }; 

      for (int i = 0; i < rga.Length - 1; i++) 
      { 
       Console.WriteLine("Comparing {0} and {1}:", i, i + 1); 
       foreach (PropertyCompareResult resultItem in Compare(rga[i], rga[i+1])) 
       { 
        Console.WriteLine(" Property name: {0} -- old: {1}, new: {2}", 
         resultItem.Name, resultItem.OldValue ?? "<null>", resultItem.NewValue ?? "<null>"); 
       } 
      } 
     } 
    } 
} 
+0

Dziękuję Peter, wciąż jestem otwarty na sugestie. Jestem nowicjuszem w tej dziedzinie, więc warto zobaczyć wszystkie możliwe sposoby. – user3788671

Powiązane problemy