C # LINQ-TO-SQL: datacontext.ChangeConflicts не показывает все конфликты - PullRequest
2 голосов
/ 08 мая 2011

Я сталкиваюсь с проблемой при работе с linq-to-sql и пытаюсь разрешить конфликты.Проблема в том, что иногда конфликт не обнаруживается.Пожалуйста, посмотрите на приведенный ниже пример кода:

// Setup the object to re-produce the problem
//
// MyObject has properties: id, my_string, my_int and version (timestamp) to enable
// conflicts detection
var context = new MyDataContext();
var obj = new MyObject();
obj.id = "1";
obj.my_string = "value";
obj.my_int    = 0;
context.MyTable.InsertOnSubmit(obj);
context.SubmitChanges();
context.dispose();

// Get 2 data contexts         
var context1 = new MyDataContext();
var context2 = new MyDataContext();

// Get 2 instances of obj - 1 from each context
var obj1= context1.MyTable.SingleOrDefault(o => o.id == "1");
var obj2= context2.MyTable.SingleOrDefault(o => o.id == "1");

// Change the values of obj1 and update it to the database
obj1.my_string= "value1";
obj1.my_int= 0;
context1.SubmitChanges();
context1.Dispose();

// Update the changes in obj2
obj2.my_string= "value2";
obj2.my_int= 1;

// Now the database contains:
//   id:        "1"
//   my_string: "value1"
//   my_int:    0

// obj2 contains:
//   id:        "1"
//   my_string: "value2"
//   my_int:    1

try
{
  context2.SubmitChanges();
}
catch(ChangeConflictException ex)
{
  LogInfo("Conflicting members:");
  context2.ChangeConflicts[0].MemberConflicts.ToList().ForEach(
                mcc=>LogInfo("Property '{0}': Database value: {1}, Current Value:{2}", mcc.Member.Name, mcc.DatabaseValue, mcc.CurrentValue)
                );
}
context2.Dispose();

В подвохе я ожидаю увидеть 3 конфликта участников: my_string, my_int и version, но я вижу только 2 конфликта участников: my_string и version.My_int не определяется как конфликт.

Если бы при создании объекта my_int настроил значение, отличное от значения, которое я присвоил obj2, конфликт обнаруживается.

Я обнаружил некоторую общность: когда значение свойства (любого свойства) исходного объекта равно значению obj1, конфликт для этого свойства не обнаруживается.

Я быхотел бы получить представление о том, как преодолеть эту проблему, чтобы конфликты были успешно обнаружены

1 Ответ

1 голос
/ 10 мая 2011

Я нашел причину проблемы. Причина, по которой я не получил конфликт для свойства "my_int", заключается в том, что он не конфликтует со значением базы данных, которое context2 "знает". Я объясню это:

Я думал, что конфликт определяется как , когда значения сохраняемого объекта не равны значениям в базе данных . ЭТО НЕ !!!!

Конфликт определяется как , когда текущее значение в базе данных не равно исходному значению, знакомому контексту . Исходное значение - это значение, которое было в базе данных при выполнении запроса выбора.

Изучив пример в моем вопросе, когда context2 выбрал данные из базы данных для создания obj2, значениями свойств были: my_string: "value", my_int: 0. Это исходные значения.

Когда я пытался сохранить данные, LINQ-TO-SQL сравнивал исходные значения со значениями базы данных. Значения базы данных в это время (после сохранения obj1): my_string: "value1", my_int: 0

В результате я получил конфликт в my_string (оригинал: «значение», база данных: «значение1»), но не в my_int (оригинал: 0, база данных: 0).

Обнаружение этого помогло мне понять, почему нет конфликта, но все же это не помогло мне решить проблему, потому что неправильное значение не было сохранено в базе данных, потому что я проанализировал только MemberChangeConflicts, который существует в ObjectChangeConflict, и если свойство, которое я проверяю, там не существует, логика проверки пропускается.

Решением было проанализировать также перечислимые измененные члены, которые предоставляют доступ ко всем измененным свойствам, и для каждого я могу получить исходное значение и новое значение.

Чтобы получить измененные члены, необходимо выполнить метод GetModifiedMembers. Этот метод находится в таблице типа данных объекта и может быть выполнен следующим образом:

 var mmc = context.MyTable.GetModifiedMembers(myobject);

Объединение конфликтов и модифицированных участников дало мне полное представление о том, что случилось с объектом, вызвавшим конфликт, и правильно его обработало.

Спасибо за Damien_The_Unbeliever за подсказку в своем комментарии.

...