Как с помощью BLToolkit можно работать с базой, использующей хоть какой-нибудь механизм оптимистической блокировки?
Я лично предпочитаю инкрементируемый столбец Version (его можно обновлять после update-а без дополнительного подзапроса), но timestamp/rowversion тоже работает.
В моих глазах эта вещь по важности находится на одном уровне с identity (в смысле — для меня лично выше ), но её поддержки out-of-the-box не планируется, я так понимаю?
Здравствуйте, Аноним, Вы писали:
А>Как с помощью BLToolkit можно работать с базой, использующей хоть какой-нибудь механизм оптимистической блокировки? А>Я лично предпочитаю инкрементируемый столбец Version (его можно обновлять после update-а без дополнительного подзапроса), но timestamp/rowversion тоже работает.
А>В моих глазах эта вещь по важности находится на одном уровне с identity (в смысле — для меня лично выше ), но её поддержки out-of-the-box не планируется, я так понимаю?
Пример на SQL?
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Оптимистическая блокировка
От:
Аноним
Дата:
11.03.10 21:48
Оценка:
Здравствуйте, IT, Вы писали:
IT>Пример на SQL?
Давно я не брал в руки шашку...
ну типа
update dbo.Person
set MiddleName = 'Jay' , Version = @version + 1
where PersonID = @personId and Version = @version
если version не подошел — труба, @@rowcount — 0.
Как вариант — можно и посложнее:
if @@rowcount = 0 and exists(select 1 from dbo.Person where PersonID = @personId)
begin-- RAISEERROR bla-bla-blaend
Прелесть в том, что если @@rowcount = 1, то в приложении Version у объекта можно смело инкрементить.
Если 0 — тогда возможны варианты, конечно, но всё вполне решабельно.
Re: Оптимистическая блокировка
От:
Аноним
Дата:
11.03.10 22:21
Оценка:
Ну и, кстати говоря, ещё один полезный фокус (хотя и несравненно менее полезный). В некоторых случаях возникает потребность как бы переопределить операцию удаления для части таблиц в базе.
В таблицу вносится столбец IsDeleted, Delete вместо удаления — помечает это свойство, как true, а все select-ы получают прибавку к WHERE в виде IsDeleted = 0
Тоже может быть решено через атрибут на поле/таблицу.
Здравствуйте, Аноним, Вы писали:
IT>>Пример на SQL? А>Давно я не брал в руки шашку... А>ну типа А>
А>update dbo.Person
А>set MiddleName = 'Jay' , Version = @version + 1
А>where PersonID = @personId and Version = @version
А>
А>если version не подошел — труба, @@rowcount — 0.
Так это как бы работает. Операции Update/Insert/Delete возвращают количество затронутых записей. Т.е. если version не подошёл, то вернётся 0 и дальше по логике хоть труба, хоть барабан.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Аноним, Вы писали:
А>Ну и, кстати говоря, ещё один полезный фокус (хотя и несравненно менее полезный). В некоторых случаях возникает потребность как бы переопределить операцию удаления для части таблиц в базе. А>В таблицу вносится столбец IsDeleted, Delete вместо удаления — помечает это свойство, как true, а все select-ы получают прибавку к WHERE в виде IsDeleted = 0 А>Тоже может быть решено через атрибут на поле/таблицу.
Как я понимаю, задача в том, чтобы не выписывать подобное ручками?
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Оптимистическая блокировка
От:
Аноним
Дата:
12.03.10 09:09
Оценка:
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Аноним, Вы писали:
А>>Ну и, кстати говоря, ещё один полезный фокус (хотя и несравненно менее полезный). В некоторых случаях возникает потребность как бы переопределить операцию удаления для части таблиц в базе. А>>В таблицу вносится столбец IsDeleted, Delete вместо удаления — помечает это свойство, как true, а все select-ы получают прибавку к WHERE в виде IsDeleted = 0 А>>Тоже может быть решено через атрибут на поле/таблицу.
IT>Как я понимаю, задача в том, чтобы не выписывать подобное ручками?
Ну как бы да
Но это просто предложение.
Re[4]: Оптимистическая блокировка
От:
Аноним
Дата:
12.03.10 09:15
Оценка:
Здравствуйте, IT, Вы писали:
IT>Так это как бы работает. Операции Update/Insert/Delete возвращают количество затронутых записей. Т.е. если version не подошёл, то вернётся 0 и дальше по логике хоть труба, хоть барабан.
Ну да. Есть только маленький нюанс — насколько я понимаю, сейчас необходимо всё сделать руками — сам переопределил запрос для update-а, сам проверил результат, сам проинкрементил Version у объекта после Update-а.
Соответственно вопрос в том — как это лучше сделать.
Ну и было бы приятно, если бы для получения этого функционала было достаточно пометить int-поле в классе атрибутом [Version].
Здравствуйте, IT, Вы писали:
IT>Как я понимаю, задача в том, чтобы не выписывать подобное ручками?
Сейчас можно очень просто обновить объект таким образом:
using (var db = new DataModel())
{
db.Update(stockItem);
}
Если же вызывать метод Update для IQueryable<T>, то приходится явно указывать все поля, т.е. теряются преимущества автоматического мэппинга, при обновлении модели (добавлении столбца) мне придется обновлять и linq запрос.
Т.е. хочется чтобы была возможность делать оптимистическую блокировку как-то так:
using (var db = new DataModel())
{
int rowsUpdated = db.Update(
si => si.ID == stockItem.ID && si.Version == stockItem.Version, // predicate for optimistic locking
stockItem); // just specify the whole object instead of explicit specifying each fieldif (rowsUpdated == 0)
throw new ConcurrencyException(...);
}
Здравствуйте, Аноним, Вы писали:
А>Ну и было бы приятно, если бы для получения этого функционала было достаточно пометить int-поле в классе атрибутом [Version].
Ну да, можно так. Только наверное лучше чтобы имя атрибута было более универсальным, т.к. для этого может использоваться и timestamp поле, а для него название атрибута [Version] мне кажется немного менее логичным что ли..
Достаточно в BLToolkit.Data.Linq.Query<T> в методы Update и Delete добавить добавление в раздел "Where" SQL-команды колонок, помеченных предложенным выше атрибутом (RowVersion).
А инкремент этого значения при обновлении — это уже другая задача, зависящая от применяемой СУБД и прочих условий.