Определение не равных значений свойств с помощью лямбды в C#

В какой-то момент моего приложения мне предоставляют словарь данных из запроса к базе данных. Я беру эти данные и экземпляр объекта и вызываю RestoreState() метод, который берет словарь данных и применяет значения к соответствующим свойствам в новом экземпляре.

Когда RestoreState() метод завершен, я затем передаю словарь значений объекту в свойство с именем OriginalValues вроде такой:

myObject.EnableChangeTracking = true;
myObject.OrginalValues = dictionaryData;

Позже пользователь вносит некоторые изменения в объект через пользовательский интерфейс и нажимает сохранить. Затем я хочу сравнить существующее состояние свойств объектов с исходным состоянием, чтобы можно было создать оператор обновления для отправки в SQL.

Проблема (и вопрос) в том, что мое лямбда-выражение для сравнения моего текущего значения свойства со значением в словаре не работает. OriginalValues словарь содержит 23 элемента, а возвращенный словарь из моего Lambda содержит 14. В моем модульном тесте я меняю только 2. Почему я получаю 12 дополнительных значений, которые не изменились?

Мой метод GetChanges:

    public Dictionary<string, object> GetChanges()
    {
        if(!EnableChangeTracking || OrginalValues==null || !OrginalValues.Any())
            return new Dictionary<string, object>();

        // Only get properties that have changed.
        var changedProperties = 
            this
            .GetType()
            .GetProperties()
            .Where(p => p.GetValue(this, null) != OrginalValues[p.Name])
            .ToDictionary(p => p.Name, p => p.GetValue(this));

        return changedProperties;
    } 

мой OriginalValues словарь содержит:

  • [0] {[AssetId, 1]} System.Collections.Generic.KeyValuePair
  • [1] {[SubFeatureId, 0]} System.Collections.Generic.KeyValuePair
  • [2] {[OrgNumber, 8555]} System.Collections.Generic.KeyValuePair
  • [3] {[LaneLocationId,]} System.Collections.Generic.KeyValuePair
  • [4] {[StatusId, 1]} System.Collections.Generic.KeyValuePair
  • [5] {[AssetCode, 1]} System.Collections.Generic.KeyValuePair
  • [6] {[Примечание. Здесь нечего видеть.]} System.Collections.Generic.KeyValuePair
  • [7] {[DateActivation, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [8] {[DateInactivation, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [9] {[EnteredBy, JS]} System.Collections.Generic.KeyValuePair
  • [10] {[DateEntered, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [11] {[CreatedBy, JS]} System.Collections.Generic.KeyValuePair
  • [12] {[updatedBy, JS]} System.Collections.Generic.KeyValuePair
  • [13] {[DateCreated, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [14] {[DateUpdated, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [15] {[IsActive, True]} System.Collections.Generic.KeyValuePair
  • [16] {[AssetAttributes, System.Collections.Generic.List`1 [FISDC.Models.AssetAttribute]]} System.Collections.Generic.KeyValuePair
  • [17] {[AssetReasons, System.Collections.Generic.List`1 [FISDC.Models.AssetReason]]} System.Collections.Generic.KeyValuePair
  • [18] {[AssetObjects, System.Collections.Generic.List`1 [FISDC.Models.AssetObject]]} System.Collections.Generic.KeyValuePair
  • [19] {[SubFeature,]} System.Collections.Generic.KeyValuePair
  • [20] {[EnableChangeTracking, False]} System.Collections.Generic.KeyValuePair
  • [21] {[IsValid, False]} System.Collections.Generic.KeyValuePair
  • [22] {[OrginalValues,]} System.Collections.Generic.KeyValuePair

и мое лямбда-выражение возвращает:

  • [0] {[AssetId, 1]} System.Collections.Generic.KeyValuePair
  • [1] {[SubFeatureId, 0]} System.Collections.Generic.KeyValuePair
  • [2] {[OrgNumber, 2222]} System.Collections.Generic.KeyValuePair
  • [3] {[StatusId, 1]} System.Collections.Generic.KeyValuePair
  • [4] {[DateActivation, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [5] {[DateInactivation, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [6] {[DateEntered, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [7] {[CreatedBy, SomeoneElse]} System.Collections.Generic.KeyValuePair
  • [8] {[DateCreated, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [9] {[DateUpdated, 21.01.2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [10] {[IsActive, True]} System.Collections.Generic.KeyValuePair
  • [11] {[EnableChangeTracking, True]} System.Collections.Generic.KeyValuePair
  • [12] {[IsValid, False]} System.Collections.Generic.KeyValuePair
  • [13] {[OrginalValues, System.Collections.Generic.Dictionary`2 [System.String, System.Object]]} System.Collections.Generic.KeyValuePair

Единственными свойствами, которые я изменил в моем модульном тесте, были OrgNumber и CreatedBy. У кого-нибудь есть идеи?

Обновить

Ниже приведен код, который я использую, чтобы обновить свойства, а затем вызвать GetChanges() метод.

        myObject.OrgNumber = "2222";
        myObject.CreatedBy = "SomeoneElse";

        myDictionary = myObject.GetChanges();

Обновление 2

Мне любопытно, если проблема в том, что мой словарь <string, object> а я сравниваю как с ссылочными, так и с не ссылочными типами? Значит, значение int сравнивается с объектом и возвращается? Я не знаю.

Обновление 3

Метод работы благодаря @TTat

    public Dictionary<string,object> OrginalValues { get; set; }

    public Dictionary<string, object> GetChanges()
    {
        if(!EnableChangeTracking || OrginalValues==null || !OrginalValues.Any())
            return new Dictionary<string, object>();

        // Only get properties that have changed.
        var changedProperties = 
            this
            .GetType()
            .GetProperties()
            .Where(p => !System.Attribute.IsDefined(p, typeof(IgnoreAttribute))
                         && !Equals(p.GetValue(this, null), OrginalValues[p.Name]))
            .ToDictionary(p => p.Name, p => p.GetValue(this));

        return changedProperties;
    } 

1 ответ

Решение

Так как ваш словарь <string, object>, != будет использовать сравнение ссылок. Использовать Equals способ проверить значение. При этом используется базовое равенство, которое будет обрабатывать для вас нулевые результаты.

Where(p => !Equals(p.GetValue(this, null), OrginalValues[p.Name]))
Другие вопросы по тегам