Update PrimaryKey или первоначальное значение
От: krupoderov  
Дата: 12.04.06 07:42
Оценка:
Есть некий класс

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 или есть кокой-то атрибут?
Re: Update PrimaryKey или первоначальное значение
От: Блудов Павел Россия  
Дата: 12.04.06 08:28
Оценка:
Здравствуйте, krupoderov, Вы писали:

Интересная идея. Теоретически наверное даже реализуемая. Только есть пара вопросов:

Если Вы ещё раз вызовете UpdateSql, то что должно произойти?
Если потом ещё раз поменяете первичный ключ и снова вызовете UpdateSql, то что должно произойти?

Тонкость в том, что "предыдущее значение" всегда должно соответствовать значению на сервере, иначе вся идея обламывается.
Следовательно нужен механизм, отслеживающий успешные изменения полей первичного ключа и обновляющих то самое пресловутое значение.
И откатывающий все обратно при откате транзикции. Я за Игоря не скажу, но по моему мнению попытка реализовать подобную систему привнесёт граблей больше, чем удобства.
Вам проще завести отдельный метод и явно менять у записей первичные ключи. Или сделать всё-таки вырожденный PK, а HouseId сделать обычным полем с уникальным индексом.
... << RSDN@Home 1.2.0 alpha rev. 642>>
Re[2]: Update PrimaryKey или первоначальное значение
От: krupoderov  
Дата: 12.04.06 09:09
Оценка:
БП>Если Вы ещё раз вызовете 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 (один логический, другой физический).
Хотя если такой функциональности не реализовано, то это самое простое и логичное решение.

Я знаю что внутрях есть старые значения атрибутов, наверху можно узнать менялся он или нет, а вот старое значение вытащить просто не смог.
Re: Update PrimaryKey или первоначальное значение
От: IT Россия linq2db.com
Дата: 12.04.06 12:20
Оценка: +1
Здравствуйте, krupoderov, Вы писали:

K>Но в параметрах @HouseId и @HouseId_W будет одинаковое значенией (AcceptChanges еще не вызывалось)

K>Как можно получить старое значение HouseId или есть кокой-то атрибут?

Технически проблему update со старым ключом на уровне библиотеки решить можно. Но хранение этого самого ключа не решается никак, разве что только в случае с извращениями с EditableObjects. Моё ИМХО — этой задачей должен заниматься прикладной код. Тем более что в случае неуспеха всегда должна быть возможность откатиться в предыдущее состояние. Я в процессе множества экспериментов пришёл к одному простому выводу — в приложении всегда должен редактироваться клон объекта, а не сам объект. После сохранения объекта в базе, клон мажно замапить на оригинальный объект или в особо клинических случаях объект можно перечитать по новой из базы.

Что касается update с двумя объектами в качестве параметров: изменённый объект и оригинальный объект, то это сделать можно. Идея очень здравая.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Update PrimaryKey или первоначальное значение
От: Блудов Павел Россия  
Дата: 13.04.06 01:21
Оценка:
Здравствуйте, krupoderov, Вы писали:

K>В случае транзакции мы просто откатываем и объект.


Просто? Просто не получится. Давайте рассмотрим такой сценарий:

Smth = db.SelectByKey(); // Smth.Key = Шило.
db.BeginTransaction();
Smth.Key = Мыло
db.Update(); // Шило => Мыло
db.Transaction.Save("SavePoint");
Smth.Key = Водка
db.Update(); // Мыло => Водка
db.Transaction.Rollback("SavePoint");  Водка => Мыло
Smth.Key = Носки
db.Update(); // Мыло => Носки
db.RollbackTransaction();  Носки => Шило


Т.е. нужно хранить предудущее значение и стек значений для каждой вложенной транзакции. И при откате находить в этом стеке нужные значения.

Причём логика первый пришёл — последний ушёл тут не годится. Вот такой код вполне корректен:
db.BeginTransaction("Transaction");
// ...
db.Transaction.Save("SavePoint");
// ...
db.RollbackTransaction("Transaction");

SavePoint просто идёт в лес. И в приведённом выше примере откат должен произойти сразу на Шило, минуя Мыло.

Важное замечание.

Сейчас транзакции в BLToolkit'е не имеют save point'ов. Хотя и SqlTransaction и OracleTransaction их имеют.
Но это не значит, что Игорь их туда никогда не добавит
... << RSDN@Home 1.2.0 alpha rev. 642>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.