MSSQL инкремент значения

220
25 января 2018, 16:25

Как инкрементировать значение поля в БД MSSQL с использованием Linq. Вариант с прочитать-прибавить-записать не подходит ввиду одновременного инкремента разными клиентами и потоками.

По ответам из комментов, попробовал сделать вот так:

public static async Task IncrementDownloadCounterAsync(Int32 id)
{
    using (LICENSE_RO3Entities db = new LICENSE_RO3Entities())
    {
        using (DbContextTransaction transaction = db.Database.BeginTransaction())
        {
            DB.Update update = await db.Updates.FindAsync(id);
            if (update != null)
            {
                update.download_counter++;
            }
            await db.SaveChangesAsync();
            transaction.Commit();
        }
    }
}
Answer 1

Для обновления одной записи никакая транзакция не нужна: EF умеет использовать оптимистическую блокировку для той же цели.

Если вы используете Core First - можно отметить свойство атрибутом [ConcurrencyCheck]. В таком случае EF при каждом обновлении записи будет дополнительно проверять что значение соответствующего атрибута в базе не изменилось.

Также можно добавить в модель свойство отмеченное атрибутом [Timestamp] типа byte[] если база данных поддерживает тип данных rowversion или его аналог. Отличие Timestamp от ConcurrencyCheck - в том, что ConcurrencyCheck только проверяется, а Timestamp еще и автоматически обновляется при любом изменении записи.

[Timestamp]
public byte[] RowVersion { get; set; }

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

Но самый нормальный способ - конечно же делать это средствами базы. EF не предоставляет способа делать это через Linq - поэтому надо использовать SQL-запрос:

db.Database.ExecuteSqlCommand("UPDATE Updates SET download_counter = download_counter + 1 WHERE Id = @p0", id);

Если есть желание изолировать вышележащие слои от SQL-кода - можно добавить этот запрос как метод контексту:

public void IncrementDownloadCounter(int id) 
{
    if (Database.ExecuteSqlCommand("UPDATE Updates SET download_counter = download_counter + 1 WHERE Id = @p0", id) == 0)
    {
        throw что-нибудь;
    }
}
READ ALSO
Изменяя значение DataGrid в другом потоке

Изменяя значение DataGrid в другом потоке

Есть DataGrid, в него заношу новый объектЕсли я в основном потоке получаю ссылку на первый Item у DataGrid, привожу его к типу и изменяю свойства, то и значения...

176
JavaScript без быдлокодинга [требует правки]

JavaScript без быдлокодинга [требует правки]

Возник вопрос по поводу изучения чистого JS и фреймворковНе раз являлся свидетелем: на форумах более-менее опытные разработчики пытаются...

312
vuejs - работа с компонентами без npm

vuejs - работа с компонентами без npm

Изучаю сейчас vuejsВ уроках для разворачивания простого приложения со структурой, представленной ниже, понадобилось поставить node

275