Здравствуйте!
Столкнулся с интересной бизнес-логико-организационной ситуацией в приложении.
Есть цепочка записей Дедушка-Родитель-Дети.
Делаю ВФ страницу, которая создает родителя и дочерние записи. Так вот, кто-то добавил на Дедушку новое ВалРул, и часть Дедушкиных записей оказалось в "нередактируемом" положении, то есть существующая комбинация значений в полях провоцирует новое ВалРул при попытке апдатировать запись по какому-либо поводу.
Ну и ладно, как это касается моей возни с новой ВФ страницей? а вот как: я не могу вставить Родителя (или даже дочернюю запись, если б такое требовалось), т.к. все эти три уровня записей связаны SumUp полям, то есть при попытки вставить Родителя, у Дедушки происходит апдатирования на SumUp поле, а Дедушку то нельзя "кантовать" из-за нового ВалРула.
(PS все даже немного сложнее, чем я описал выше: я не могу вставить Дочернуюю запись из-за проблем на Дедушки, а связаны они цепочкой формульных полей, что в общем то обычная структура для приложения)
Получается на своей ВФ странице я вывожу пользователю Ошубку, которая вообще не относится к тому что он делает и должен знать, эта ошибка - это сообщение ВалРула от дедушкиной записи...
вот сижу и думаю, как все это правильно организовать? Этим, ведь, людям (Биз аналитикам) можно сказать чтоб острожнее создавали ВалРулы, но ведь на это нельзя надеяться...
И к слову, как вы отрабатываете ситуацию последовательной вставки Родителя и Дочерней записи, т.е. проблемы могут возникнуть если вставка Дочерней записи "обломилась", а родительская запись то вставилась, а она не имеет смысла без дочерних...
так пойдет?
Savepoint sp = Database.setSavepoint();
try{
insert parent;child.MyParent__c = parent.id;
insert child;
}
catch(exception ex){
Database.rollback(sp);
}
Здравствуйте! Столкнулся с интересной бизнес-логико-организационной ситуацией в приложении. Есть цепочка записей Дедушка-Родитель-Дети. Делаю ВФ страницу, которая создает родителя и дочерние записи. Так вот, кто-то добавил на Дедушку новое ВалРул, и часть Дедушкиных записей оказалось в "нередактируемом" положении, то есть существующая комбинация значений в полях провоцирует новое ВалРул при попытке апдатировать запись по какому-либо поводу. Ну и ладно, как это касается моей возни с новой ВФ страницей? а вот как: я не могу вставить Родителя (или даже дочернюю запись, если б такое требовалось), т.к. все эти три уровня записей связаны SumUp полям, то есть при попытки вставить Родителя, у Дедушки происходит апдатирования на SumUp поле, а Дедушку то нельзя "кантовать" из-за нового ВалРула. [i](PS все даже немного сложнее, чем я описал выше: я не могу вставить Дочернуюю запись из-за проблем на Дедушки, а связаны они цепочкой формульных полей, что в общем то обычная структура для приложения)[/i] Получается на своей ВФ странице я вывожу пользователю Ошубку, которая вообще не относится к тому что он делает и должен знать, эта ошибка - это сообщение ВалРула от дедушкиной записи... вот сижу и думаю, как все это правильно организовать? Этим, ведь, людям (Биз аналитикам) можно сказать чтоб острожнее создавали ВалРулы, но ведь на это нельзя надеяться... И к слову, как вы отрабатываете ситуацию последовательной вставки Родителя и Дочерней записи, т.е. проблемы могут возникнуть если вставка Дочерней записи "обломилась", а родительская запись то вставилась, а она не имеет смысла без дочерних... так пойдет? [code]Savepoint sp = Database.setSavepoint(); try{ insert parent; child.MyParent__c = parent.id; insert child; } catch(exception ex){ Database.rollback(sp); }[/code]
Отличную тему поднял. Сам когда начинал с SF столкнулся с такой проблемой что при наличии Rollup Summary родитель тоже обновляется при обновлении подчиненного. И если родитель не может обновиться то валится обновление у подчиненного.
Я тогда был еще неопытен, поэтому реально ломал голову полдня и даже хотел отписать старшим лидам что SF неисправен. А вот как оно вышло в итоге.
Честно так и не нашел подходящего варианта как это обойти. Но в моем случае это и не нужно было - родители просто должны были быть валидными.
Делать Savepoint для Salesforce необязательно (да честно и не встречалось мне таких ситуаций где он нужен был). При exception вся транзакция за этот вызов откатывается. Поэтому даже если отвалится последняя DML в цепочке откатятся все предыдущие.
Не уверен, но попробуй Database.insert(..., false). Может то что отваливается родитель не повлияет на вставку подчиненного. !Но это предположение.
Отличную тему поднял. Сам когда начинал с SF столкнулся с такой проблемой что при наличии Rollup Summary родитель тоже обновляется при обновлении подчиненного. И если родитель не может обновиться то валится обновление у подчиненного. Я тогда был еще неопытен, поэтому реально ломал голову полдня и даже хотел отписать старшим лидам что SF неисправен. А вот как оно вышло в итоге. Честно так и не нашел подходящего варианта как это обойти. Но в моем случае это и не нужно было - родители просто должны были быть валидными. Делать Savepoint для Salesforce необязательно (да честно и не встречалось мне таких ситуаций где он нужен был). При exception вся транзакция за этот вызов откатывается. Поэтому даже если отвалится последняя DML в цепочке откатятся все предыдущие. Не уверен, но попробуй Database.insert(..., false). Может то что отваливается родитель не повлияет на вставку подчиненного. !Но это предположение.
к родителям-записям нет вопросов, есть вопрос к нам людям:
(1) как организационно избежать таких ловушек? объяснять Биз аналитикам проблему? я кстати видел подобную ситуацию спровоцированную пользователем: они поменяли РекТайп на одной записи, после чего где-то связь между записями перестала быть валидной (из-за фильтра на Лук-Апе) и все "дерево" дочерних записей "зависло"...
(2) как избежать показа пользователям эррор сообщений, по части их не касающихся? Например, показывать только те ДМЛ сообщения, которые относятся непосредственно к вставляемым пользователем записям, а не свалившиеся откуда-то сверху (эти сообщения перекрывать специальным кастомным сообщением)?
как это откатывается? ведь уже исполнившийся код в try{} не откатывается назад при уходе в catch?
[quote="Dmitry Shnyrev"]родители просто должны были быть валидными[/quote] к родителям-записям нет вопросов, есть вопрос к нам людям: (1) как организационно избежать таких ловушек? объяснять Биз аналитикам проблему? я кстати видел подобную ситуацию спровоцированную пользователем: они поменяли РекТайп на одной записи, после чего где-то связь между записями перестала быть валидной (из-за фильтра на Лук-Апе) и все "дерево" дочерних записей "зависло"... (2) как избежать показа пользователям эррор сообщений, по части их не касающихся? Например, показывать только те ДМЛ сообщения, которые относятся непосредственно к вставляемым пользователем записям, а не свалившиеся откуда-то сверху (эти сообщения перекрывать специальным кастомным сообщением)? [quote="Dmitry Shnyrev"]При exception вся транзакция за этот вызов откатывается.[/quote] как это откатывается? ведь уже исполнившийся код в try{} не откатывается назад при уходе в catch?
ДО try не откатывается, а внутри try откатывается. Если я ничего не путаю. Проверь, расскажешь
Да, отлавливать DMLexception и показывать кастомное сообщение.
Да и вообще пользователям всегда показывать только кастомные сообщения и только те, которые их касаются. При любой исключительной ситуации выводить общее сообщение "Server error. Please contact administrator", а саму ошибку писать в логи чтобы потом разобраться.
[quote="Den Brown"]как это откатывается? ведь уже исполнившийся код в try{} не откатывается назад при уходе в catch?[/quote] ДО try не откатывается, а внутри try откатывается. Если я ничего не путаю. Проверь, расскажешь :) [quote="Den Brown"](2) как избежать показа пользователям эррор сообщений, по части их не касающихся?[/quote] Да, отлавливать DMLexception и показывать кастомное сообщение. Да и вообще пользователям всегда показывать только кастомные сообщения и только те, которые их касаются. При любой исключительной ситуации выводить общее сообщение "Server error. Please contact administrator", а саму ошибку писать в логи чтобы потом разобраться.
Побольше "защит от дурака" чтобы не возникало таких ловушек. Иначе если не смог предусмотреть выводить сообщения как я написал выше, чтобы пользователь не ломал голову.
Жаль у SF разработчиков не хватает знаний из других областей web dev.
Например в любой языке учат что ошибки выкидывать надо только при debug=true, а в остальных случаях Internal Error. А в SF мы привыкли что каждый пользователь минимум администратор и выкидываем ошибки еще со stack trace прямо на страницу.
Как и с транзакциями тоже расслабились - не знаем что и когда откатывается. На других платформах если SQL запрос произошел, то он уже произошел и ничего не вернуть, поэтому разработчики сами заботятся о транзакциях и целостности данных. А в SF все на блюдичке - получил exception, данные откатились и никто не думает какие данные и насколько далеко откатились.
[quote="Den Brown"]как организационно избежать таких ловушек? объяснять Биз аналитикам проблему?[/quote] Побольше "защит от дурака" чтобы не возникало таких ловушек. Иначе если не смог предусмотреть выводить сообщения как я написал выше, чтобы пользователь не ломал голову. Жаль у SF разработчиков не хватает знаний из других областей web dev. Например в любой языке учат что ошибки выкидывать надо только при debug=true, а в остальных случаях Internal Error. А в SF мы привыкли что каждый пользователь минимум администратор и выкидываем ошибки еще со stack trace прямо на страницу. Как и с транзакциями тоже расслабились - не знаем что и когда откатывается. На других платформах если SQL запрос произошел, то он уже произошел и ничего не вернуть, поэтому разработчики сами заботятся о транзакциях и целостности данных. А в SF все на блюдичке - получил exception, данные откатились и никто не думает какие данные и насколько далеко откатились.
на объекте вставляемой записи могут быть собственные Вал рулсы. Как я понимаю, их сообщения, необходимые пользователю, вернутся в DMLexception. Поэтому ставить сообщение-"загрушку" для всех Еxception не получится...
[quote="Dmitry Shnyrev"]Да, отлавливать DMLexception и показывать кастомное сообщение. [/quote] на объекте вставляемой записи могут быть собственные Вал рулсы. Как я понимаю, их сообщения, необходимые пользователю, вернутся в DMLexception. Поэтому ставить сообщение-"загрушку" для всех Еxception не получится...
Проверил в "Execute Anonymous", рассказываю:
если
insert parent;
child.MyParent__c = parent.id;
insert child;
взяты в Трай, то несмотря на DMLException по собственному Вал рулу у child, parent еще как вставляется...
(и Savepoint решает проблему)
а вот если insert-ы делаются без Трая, "голиком", то код выпадает в исключение и ничего не сохраняется.
кстати, что если ошибка пришла с родительской запси по Вал рулу или с собственого Вал рула, то все одно это будет один тип исключения DMLException, и так просто сообщения не разрулить: что показывать пользователю, что нет. Придется читать мэсаджи и пропускать только годные, но это как то нехорошо, так подразумевает хардкод...
[quote="Dmitry Shnyrev"]ДО try не откатывается, а внутри try откатывается. Если я ничего не путаю. Проверь, расскажешь[/quote] Проверил в "Execute Anonymous", рассказываю: если [code] insert parent; child.MyParent__c = parent.id; insert child;[/code] взяты в Трай, то несмотря на DMLException по собственному Вал рулу у child, parent еще как вставляется... [i](и Savepoint решает проблему)[/i] а вот если insert-ы делаются без Трая, "голиком", то код выпадает в исключение и ничего не сохраняется. кстати, что если ошибка пришла с родительской запси по Вал рулу или с собственого Вал рула, то все одно это будет один тип исключения DMLException, и так просто сообщения не разрулить: что показывать пользователю, что нет. Придется читать мэсаджи и пропускать только годные, но это как то нехорошо, так подразумевает хардкод...
Хм. Очень интересно. Я думал что работает как раз наоборот.
[quote="Den Brown"]взяты в Трай, то несмотря на DMLException по собственному Вал рулу у child, parent еще как вставляется... (и Savepoint решает проблему)[/quote] Хм. Очень интересно. Я думал что работает как раз наоборот.