2014-01-08 3 views
2

В идеале, я хотел бы иметь:ServiceStack Linq поля слияния и частичное обновление

public user Update(User dto) { 
     var user = userRepository.GetUserById(dto.Id); 
     var mergedFields = Merge(user, dto); //my dream function 
     userRepository.UpdateOnly(user, mergedFields) 
         .Where(u => u.Id == user.Id); //OrmLite UpdateOnly func 
     return user; 
    } 

Где Merge моя функция Deam, которая возвращает Linq выражение:

Expression<Func<T, TKey>> Merge(T target, T source)

Так, Merge знает что было обновлено от Т-источника до цели Т. Обновите значения этих свойств в целевом объекте и верните эти обновленные свойства в виде выражения Linq для OrmLite UpdateOnly.

Однако, я тяну свои волосы, и я не могу понять, как написать эту функцию Merge. Пожалуйста, бросьте мне помощь!

Спасибо!


Ref: ServiceStack OrmLite является light weight ORM. Это UpdateOnly функция принимает Linq выражение как это:

.UpdateOnly(new User {FirstName="admin", LastName="my", OtherStuff="etc..."}, 
      u => {u.FirstName, u.LastName}).Where(u => u.Id == 123); 

ответ

3

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

Я думаю, что UpdateNonDefaults OrmLite лучше подходит для вашей задачи.

Ваше действие по обновлению должно получать только изменения существующей записи в DTO, а не полный объект. Поэтому делать это, должно быть достаточно:

db.UpdateNonDefaults(dto, u => u.Id == 123); 

Результаты в SQL:

UPDATE "User" SET "FirstName" = 'admin', "LastName" = 'my' WHERE ("UserId" = 123); 

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


Если вы были мертвы набор на проверку измененных полей против оригинала, то вы можете сделать это без сложности выражения Linq. Ваша функция Merge может сделать это (псевдокод):

public T Merge(T target, T source) 
{ 
  1. Создать новый объект по умолчанию для возвращения. то естьvar result = default(T);
  2. Отражать ваши T target общие свойства:

    foreach(var property in target.GetType().GetPublicProperties()){ 
    

    С каждым отражено свойство:

    1. Определить изменилось ли значение используя EqualityComparer: if(!EqualityComparer<FieldType>.Default.Equals(targetField, sourceField))

    2. Установите значение на объект result, если стоимость e отличается.

  3. Возврат result объект. У него будут только изменения.

Теперь с помощью UpdateNonDefaults в результате обеспечит только изменения включены в SQL обновления.


Стоит ли проверять измененные поля? Возможно, вы должны запустить некоторые тесты. Помните, что проверка включает:

  • Запрос базы данных для всей существующей записи.
  • Отражающие свойства объекта цели и источника.
  • Выполнение сравнения значений.
  • Создание выражения Linq или нового объекта для отслеживания изменений.
  • Выполнение функции обновления.

Если вы застряли в определении изменений на ваших объектах, может помочь the answers in this question.

Надеюсь, это поможет.

+1

Это очень подробный ответ! Спасибо, я попробую решение и расскажу вам, как это работает позже. – Tom

+1

@Tom Спасибо. Надеюсь, ты получишь это. – Scott

Смежные вопросы