public abstract class House
{
[PrimaryKey]
public abstract int HouseId {get;set;}
public abstract string Address {get;set;}
}
Если я поменяю HouseId, а потом вызову UpdateSql, по собственно ничего не получу, т.к.
сгенерируеться подобный запрос
UPDATE House SET HouseId = @HouseId, Address = @Address WHERE HouseId = @HouseId_W
Но в параметрах @HouseId и @HouseId_W будет одинаковое значенией (AcceptChanges еще не вызывалось)
Как можно получить старое значение HouseId или есть кокой-то атрибут?
Интересная идея. Теоретически наверное даже реализуемая. Только есть пара вопросов:
Если Вы ещё раз вызовете UpdateSql, то что должно произойти?
Если потом ещё раз поменяете первичный ключ и снова вызовете UpdateSql, то что должно произойти?
Тонкость в том, что "предыдущее значение" всегда должно соответствовать значению на сервере, иначе вся идея обламывается.
Следовательно нужен механизм, отслеживающий успешные изменения полей первичного ключа и обновляющих то самое пресловутое значение.
И откатывающий все обратно при откате транзикции. Я за Игоря не скажу, но по моему мнению попытка реализовать подобную систему привнесёт граблей больше, чем удобства.
Вам проще завести отдельный метод и явно менять у записей первичные ключи. Или сделать всё-таки вырожденный PK, а HouseId сделать обычным полем с уникальным индексом.
... << RSDN@Home 1.2.0 alpha rev. 642>>
Re[2]: Update PrimaryKey или первоначальное значение
БП>Если Вы ещё раз вызовете UpdateSql, то что должно произойти? БП>Если потом ещё раз поменяете первичный ключ и снова вызовете UpdateSql, то что должно произойти?
преставим ситуацию
UPDATE House SET HouseId = 10 WHERE HouseId=5
У нас меняется PK с 5 на 10
при повторном вызове этой команды ничего не произойдет, т.к. записи с HouseId=5 уже нет
Что в общем не противоречил логике, т.к. не были применение изменений.
Старое значение PK в объекте сохраняеться пока не вызвана AcceptChanges()
а т.к. сначала идет Update а потом AcceptChanges() то пример такой
Изначально HouseId = 5
Пример 1.
h.HouseId = 10
UpdateSql(h) -> генерирует UPDATE House SET HouseId = 10 WHERE HouseId=5
// Это уже нарушение логики, т.к. в базу уже нет HouseId=5
h.HouseId = 11
UpdateSql(h) -> генерирует UPDATE House SET HouseId = 11 WHERE HouseId=5
Пример 2.
h.HouseId = 10
UpdateSql(h) -> генерирует UPDATE House SET HouseId = 10 WHERE HouseId=5
h.AcceptChanges()
// все нормально, т.к. старое значение HouseId=10 после AcceptChanges()
h.HouseId = 11
UpdateSql(h) -> генерирует UPDATE House SET HouseId = 11 WHERE HouseId=10
h.AcceptChanges()
В случае транзакции мы просто откатываем и объект.
БП>Тонкость в том, что "предыдущее значение" всегда должно соответствовать значению на сервере, иначе вся идея обламывается. БП>Следовательно нужен механизм, отслеживающий успешные изменения полей первичного ключа и обновляющих то самое пресловутое значение. БП>И откатывающий все обратно при откате транзикции. Я за Игоря не скажу, но по моему мнению попытка реализовать подобную систему привнесёт граблей больше, чем удобства. БП>Вам проще завести отдельный метод и явно менять у записей первичные ключи. Или сделать всё-таки вырожденный PK, а HouseId сделать обычным полем с уникальным индексом.
Не охота просто иметь ненармализованную БД где будут кучи PK (один логический, другой физический).
Хотя если такой функциональности не реализовано, то это самое простое и логичное решение.
Я знаю что внутрях есть старые значения атрибутов, наверху можно узнать менялся он или нет, а вот старое значение вытащить просто не смог.
Здравствуйте, krupoderov, Вы писали:
K>Но в параметрах @HouseId и @HouseId_W будет одинаковое значенией (AcceptChanges еще не вызывалось) K>Как можно получить старое значение HouseId или есть кокой-то атрибут?
Технически проблему update со старым ключом на уровне библиотеки решить можно. Но хранение этого самого ключа не решается никак, разве что только в случае с извращениями с EditableObjects. Моё ИМХО — этой задачей должен заниматься прикладной код. Тем более что в случае неуспеха всегда должна быть возможность откатиться в предыдущее состояние. Я в процессе множества экспериментов пришёл к одному простому выводу — в приложении всегда должен редактироваться клон объекта, а не сам объект. После сохранения объекта в базе, клон мажно замапить на оригинальный объект или в особо клинических случаях объект можно перечитать по новой из базы.
Что касается update с двумя объектами в качестве параметров: изменённый объект и оригинальный объект, то это сделать можно. Идея очень здравая.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Update PrimaryKey или первоначальное значение
SavePoint просто идёт в лес. И в приведённом выше примере откат должен произойти сразу на Шило, минуя Мыло.
Важное замечание.
Сейчас транзакции в BLToolkit'е не имеют save point'ов. Хотя и SqlTransaction и OracleTransaction их имеют.
Но это не значит, что Игорь их туда никогда не добавит