[linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 12.09.14 08:17
Оценка:
Получили из базы объект, поработали с ним в бизнес логике, теперь надо сохранить его обратно. Но в таблице базы есть поле timestamp, которое меняется при изменении записи в таблице. То есть, сохранять изменения в базу нельзя, если timestamp в объекте и в базе различаются, то есть, запись изменилась другим человеком, скажем.

Не получается добавить атомарную проверку.

Так не работает:
db.Products.Where(p => p.timestamp == product.timestamp).Update(p => p, product);


Так тоже не работает:
db.Products.Update(p => p.timestamp == product.timestamp, p => product );


И так не работает:
db.Where<DB, Product, DB>(p => p.timestamp == product.timestamp).Update(product);


Работает только так, но без проверки на измененный timestamp:
db.Update(product);


Можно как-то сделать?
Instagram
Re: [linq2db] db.Update() с условием
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.09.14 09:48
Оценка:
Здравствуйте, FireShock, Вы писали:

FS>Получили из базы объект, поработали с ним в бизнес логике, теперь надо сохранить его обратно. Но в таблице базы есть поле timestamp, которое меняется при изменении записи в таблице. То есть, сохранять изменения в базу нельзя, если timestamp в объекте и в базе различаются, то есть, запись изменилась другим человеком, скажем.


Транзакции вручную?

FS>Так не работает:

FS>
FS>db.Products.Where(p => p.timestamp == product.timestamp).Update(p => p, product);
FS>


Что значит "не работает"?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[2]: [linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 12.09.14 09:59
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Транзакции вручную?


Двумя операциями? Сначала прочесть из базы, потом сравнить и потом, если совпали, записать?

AVK>Что значит "не работает"?


Не может из этого всего создать SQL-запрос.
Instagram
Re[3]: [linq2db] db.Update() с условием
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.09.14 10:01
Оценка:
Здравствуйте, FireShock, Вы писали:

AVK>>Транзакции вручную?

FS>Двумя операциями? Сначала прочесть из базы, потом сравнить и потом, если совпали, записать?

Можно и так.

AVK>>Что значит "не работает"?

FS>Не может из этого всего создать SQL-запрос.

Надо два раза написать ответ чтобы получить точный текст исключения?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: [linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 12.09.14 10:16
Оценка:
Здравствуйте, AndrewVK, Вы писали:

FS>>Двумя операциями? Сначала прочесть из базы, потом сравнить и потом, если совпали, записать?

AVK>Можно и так.
Проверю, а в это время другой сервис изменит запись в базе и моя проверка будет лишней и неверной.

AVK>Надо два раза написать ответ чтобы получить точный текст исключения?



На эти C#-коды:
int count = db.DeliveryOrders.Where(o => o.RowVersion == deliveryOrder.RowVersion).Update(o => deliveryOrder);


int count = db.DeliveryOrders
              .Where(o => o.DeliveryOrderId == deliveryOrder.DeliveryOrderId)
              .Where(o => o.RowVersion == deliveryOrder.RowVersion)
              .Update(o => deliveryOrder);


такой Exception:
'value(Mxm.Data.Models.Orders.OrderRepository+<>c__DisplayClass54).deliveryOrder' cannot be converted to SQL.

   в LinqToDB.Linq.Builder.ExpressionContext.ConvertToSql(Expression expression, Int32 level, ConvertFlags flags)
   в LinqToDB.Linq.Builder.UpdateBuilder.BuildSetter(ExpressionBuilder builder, BuildInfo buildInfo, LambdaExpression setter, IBuildContext into, List`1 items, IBuildContext sequence)
   в LinqToDB.Linq.Builder.UpdateBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.ExpressionBuilder.Build[T]()
   в LinqToDB.Linq.Query`1.GetQuery(IDataContextInfo dataContextInfo, Expression expr)
   в LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression expression, Boolean cache)
   в LinqToDB.Linq.ExpressionQuery`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   в LinqToDB.LinqExtensions.Update[T](IQueryable`1 source, Expression`1 setter)
   в Mxm.Data.Models.Orders.OrderRepository.<>c__DisplayClass54.<UpdateDeliveryOrderAsync>b__53() в c:\Tfs\mxm\Dev\Search\Data Models\Mxm.Data.Models\Orders\Orders\OrderRepository.cs:строка 264
   в System.Threading.Tasks.Task.InnerInvoke()
   в System.Threading.Tasks.Task.Execute()


На этот код
int count = db.DeliveryOrders
              .Where(o => o.DeliveryOrderId == deliveryOrder.DeliveryOrderId)
              .Where(o => o.RowVersion == deliveryOrder.RowVersion)
              .Set(o => o, deliveryOrder)
              .Update();


такой Exception:
Member expression expected for the 'Set' statement.

   в LinqToDB.Linq.Builder.UpdateBuilder.ParseSet(ExpressionBuilder builder, BuildInfo buildInfo, LambdaExpression extract, Expression update, IBuildContext select, List`1 items)
   в LinqToDB.Linq.Builder.UpdateBuilder.Set.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.UpdateBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   в LinqToDB.Linq.Builder.ExpressionBuilder.Build[T]()
   в LinqToDB.Linq.Query`1.GetQuery(IDataContextInfo dataContextInfo, Expression expr)
   в LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression expression, Boolean cache)
   в LinqToDB.Linq.ExpressionQuery`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   в LinqToDB.LinqExtensions.Update[T](IUpdatable`1 source)
   в Mxm.Data.Models.Orders.OrderRepository.<>c__DisplayClass54.<UpdateDeliveryOrderAsync>b__53() в c:\Tfs\mxm\Dev\Search\Data Models\Mxm.Data.Models\Orders\Orders\OrderRepository.cs:строка 245
   в System.Threading.Tasks.Task.InnerInvoke()
   в System.Threading.Tasks.Task.Execute()


На такой код
int count = db.Where<OrdersDB, DeliveryOrder, OrdersDB>(o => o.RowVersion == deliveryOrder.RowVersion).Update(deliveryOrder);


Такой:
Операция является недопустимой из-за текущего состояния объекта.

   в LinqToDB.LinqExtensions.Where[TOutput,TSource,TInput](TInput source, Func`2 predicate)
   в Mxm.Data.Models.Orders.OrderRepository.<>c__DisplayClass55.<UpdateDeliveryOrderAsync>b__53() в c:\Tfs\mxm\Dev\Search\Data Models\Mxm.Data.Models\Orders\Orders\OrderRepository.cs:строка 251
   в System.Threading.Tasks.Task.InnerInvoke()
   в System.Threading.Tasks.Task.Execute()
Instagram
Re[5]: [linq2db] db.Update() с условием
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.09.14 10:21
Оценка:
Здравствуйте, FireShock, Вы писали:

FS>Здравствуйте, AndrewVK, Вы писали:

FS>На эти C#-коды:
FS>
FS>int count = db.DeliveryOrders.Where(o => o.RowVersion == deliveryOrder.RowVersion).Update(o => deliveryOrder);
FS>


А на это тоже самое получаешь:
db.Where<DB, Product, DB>(p => p.timestamp == product.timestamp).Update(product);

?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[6]: [linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 12.09.14 10:30
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>А на это тоже самое получаешь:

AVK>
AVK>db.Where<DB, Product, DB>(p => p.timestamp == product.timestamp).Update(product);
AVK>

AVK>?

Такой:
Операция является недопустимой из-за текущего состояния объекта.

   в LinqToDB.LinqExtensions.Where[TOutput,TSource,TInput](TInput source, Func`2 predicate)
   в Mxm.Data.Models.Orders.OrderRepository.<>c__DisplayClass55.<UpdateDeliveryOrderAsync>b__53() в c:\Tfs\mxm\Dev\Search\Data Models\Mxm.Data.Models\Orders\Orders\OrderRepository.cs:строка 251
   в System.Threading.Tasks.Task.InnerInvoke()
   в System.Threading.Tasks.Task.Execute()


Код всего метода:
        public async Task UpdateDeliveryOrderAsync(DeliveryOrder deliveryOrder)
        {
            await Task.Run(() =>
            {
                using (var db = new OrdersDB())
                {
                    int count = db.Where<OrdersDB, DeliveryOrder, OrdersDB>(o => o.RowVersion == deliveryOrder.RowVersion).Update(deliveryOrder);

                    if (count != 1)
                    {
                        throw new UpdateException();
                    }
                }
            });
        }
Instagram
Re: [linq2db] db.Update() с условием
От: Rinbe Россия  
Дата: 12.09.14 10:42
Оценка:
Откуда взялся объект product, попробуйте в место него использовать DateTime.
Re[2]: [linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 12.09.14 10:46
Оценка:
Здравствуйте, Rinbe, Вы писали:

R>Откуда взялся объект product, попробуйте в место него использовать DateTime.

Не понял
Instagram
Re[3]: [linq2db] db.Update() с условием
От: Rinbe Россия  
Дата: 12.09.14 10:50
Оценка:
Здравствуйте, FireShock, Вы писали:

FS>Здравствуйте, Rinbe, Вы писали:

R>>Откуда взялся объект product, попробуйте в место него использовать DateTime.
FS>Не понял

 var dateTime=product.timestamp;
 db.Products.Where(p => p.timestamp == dateTime).Update(p => p, product);


Вот так.
Re[4]: [linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 12.09.14 10:55
Оценка:
Здравствуйте, Rinbe, Вы писали:

R>
R> var dateTime=product.timestamp;
R> db.Products.Where(p => p.timestamp == dateTime).Update(p => p, product);
R>

R>Вот так.

Не, не получилось. Та же ошибка — не может представить это в виде SQL-скрипта.
Instagram
Re[5]: [linq2db] db.Update() с условием
От: Rinbe Россия  
Дата: 12.09.14 11:39
Оценка: 2 (1)
Здравствуйте, FireShock, Вы писали:

FS>Здравствуйте, Rinbe, Вы писали:


R>>
R>> var dateTime=product.timestamp;
R>> db.Products.Where(p => p.timestamp == dateTime).Update(p => p, product);
R>>

R>>Вот так.

FS>Не, не получилось. Та же ошибка — не может представить это в виде SQL-скрипта.


Примет отсюда: если поможет:

using (var db = new DbNorthwind())
{
  db.Product
    .Where(p => p.ProductID == product.ProductID)
    .Set(p => p.Name, product.Name)
    .Set(p => p.UnitPrice, product.UnitPrice)
    .Update();
}
Re[6]: [linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 12.09.14 11:51
Оценка:
Здравствуйте, Rinbe, Вы писали:

R>
R>using (var db = new DbNorthwind())
R>{
R>  db.Product
R>    .Where(p => p.ProductID == product.ProductID)
R>    .Set(p => p.Name, product.Name)
R>    .Set(p => p.UnitPrice, product.UnitPrice)
R>    .Update();
R>}
R>


Да, такой вариант знаю. Он подходит, да. Только для каждого типа мне придется перечислять все поля в Set, чего не хотелось бы.
Instagram
Re[7]: [linq2db] db.Update() с условием
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 12.09.14 15:58
Оценка:
Здравствуйте, FireShock, Вы писали:

FS>Операция является недопустимой из-за текущего состояния объекта.


public static TOutput Where<TOutput,TSource,TInput>(this TInput source, Func<TSource,bool> predicate)
{
    throw new InvalidOperationException();
}


Очевидно что звать этот метод можно только внутри ExpressionTree, а ты дергаешь его напрямую.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: [linq2db] db.Update() с условием
От: FireShock Россия  
Дата: 13.09.14 16:16
Оценка:
Здравствуйте, AndrewVK, Вы писали:

FS>>Операция является недопустимой из-за текущего состояния объекта.

AVK>
AVK>public static TOutput Where<TOutput,TSource,TInput>(this TInput source, Func<TSource,bool> predicate)
AVK>{
AVK>    throw new InvalidOperationException();
AVK>}
AVK>


AVK>Очевидно что звать этот метод можно только внутри ExpressionTree, а ты дергаешь его напрямую.


Да, это просто я показал, что метод нащупал, но как использовать — еще не понял. В понедельник вернусь к попыткам.
Instagram
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.