Информация об изменениях

Сообщение Re[18]: Блокировки в бизнес-слое от 04.10.2017 7:57

Изменено 04.10.2017 7:59 Poul_Ko

Re[18]: Блокировки в бизнес-слое
Здравствуйте, Sinclair, Вы писали:
S>Хотелось бы убедительный пример.
100%-но убедительный пример привести не смогу, так как конкретно это технологией не пользовался и реального опыта её применения не имею.
Но могу описать на основании каких представлений у меня сложилось озвученное мнение.
Во-первых, то что бизнес-сущности не всегда один-к-одному соответствуют таблицам я думаю вы согласитесь. В простейших случаях это следствие преднамеренной денормализации (храним список Id строкой, не охота городить таблицу; слабоструктурированные динамические данные — храним JSON в строке; ...). Работу с такими штуками на уровне linq не выразить.
Во-вторых, поведение часто бывает динамическим. Давайте разовьём пример с заказами. Пусть всего в системе у заказа может быть пять способов его оплаты. Кроме того, заказ может входить в некие программы поставок двух типов (а может и не входить). Грубо говоря, это нам даёт максимум 3х5=15 вариаций поведения на каждый аспект заказа. Окей, происходит бизнес-операция — изменение заказа, включающее в себя изменение способа оплаты и перенос в программу поставок. Рассмотрим один из аспектов — стоимость заказа. Стоимость определяется ценой (которая зависит от способа оплаты) и скидкой (которая зависит от программы поставок). В итоговом запросе мы должны получить что-то вроде
UPDATE order SET
  ...
  Cost = x.Price * quantity * y.discount,
  ...
FROM Orders
    INNER JOIN PriceListFromPaymentMethod x ON ....
    INNER JOIN SupplyPrograms y ON ...
    ...

Это и есть одна из 15 вариаций, и только для свойства Cost.

Когда всё на сущностях, то всё просто. Способ определения цены — это абстракция (некая стратегия), способ определения скидки — тоже. Имплементации смотрят на сущность сущность заказа и вычисляют значение по соответствующему алгоритму. Первая стратегия выдаёт "используйте цену 1000", вторая — "используйте скидку 10%". Код, выполняющий операцию, посчитал итоговую стоимость (900), проставил её в сущность. По другим аспектам отработали свои стратегии, заполнились остальные свойства. В итоге свойства сущности были изменены как надо, дёргаем DAL, он всё сохранил, красота.
Теперь как это провернуть на linq? Вижу два варианта.
а) Какие-то динамические запросы... Каждая стратегия вместо того чтобы просто "взять и посчитать" будет куда-то добавлять свою часть запроса. В итоге будет построен какой-то огромный запрос, которые таки да, одной операцией всё пересчитает и обновит. Но зачем эта промежуточная модель? Попробуйте её отладить...
б) Можно апдейтить свойства по одному — одним запросом обновили цену заказа, другим — другое свойство. Будет ли это просто, понятно и эффективно? Тоже сомневаюсь. Какие там ещё проблемы всплывут в конкурентной среде? Теоретически ведь можем в разных запросах использовать одни и те же данные — значит уже нужен repeatable read...
Re[18]: Блокировки в бизнес-слое
Здравствуйте, Sinclair, Вы писали:
S>Хотелось бы убедительный пример.
100%-но убедительный пример привести не смогу, так как конкретно это технологией не пользовался и реального опыта её применения не имею.
Но могу описать на основании каких представлений у меня сложилось озвученное мнение.
Во-первых, то что бизнес-сущности не всегда один-к-одному соответствуют таблицам я думаю вы согласитесь. В простейших случаях это следствие преднамеренной денормализации (храним список Id строкой, не охота городить таблицу; слабоструктурированные динамические данные — храним JSON в строке; ...). Работу с такими штуками на уровне linq не выразить.
Во-вторых, поведение часто бывает динамическим. Давайте разовьём пример с заказами. Пусть всего в системе у заказа может быть пять способов его оплаты. Кроме того, заказ может входить в некие программы поставок двух типов (а может и не входить). Грубо говоря, это нам даёт максимум 3х5=15 вариаций поведения на каждый аспект заказа. Окей, происходит бизнес-операция — изменение заказа, включающее в себя изменение способа оплаты и перенос в программу поставок. Рассмотрим один из аспектов — стоимость заказа. Стоимость определяется ценой (которая зависит от способа оплаты) и скидкой (которая зависит от программы поставок). В итоговом запросе мы должны получить что-то вроде
UPDATE order SET
  ...
  Cost = x.Price * quantity * y.discount,
  ...
FROM Orders
    INNER JOIN PriceListFromPaymentMethod x ON ....
    INNER JOIN SupplyPrograms y ON ...
    ...

Это и есть одна из 15 вариаций, и только для свойства Cost.

Когда всё на сущностях, то всё просто. Способ определения цены — это абстракция (некая стратегия), способ определения скидки — тоже. Имплементации смотрят на сущность заказа и вычисляют значение по соответствующему алгоритму. Первая стратегия выдаёт "используйте цену 1000", вторая — "используйте скидку 10%". Код, выполняющий операцию, посчитал итоговую стоимость (900), проставил её в сущность. По другим аспектам отработали свои стратегии, заполнились остальные свойства. В итоге свойства сущности были изменены как надо, дёргаем DAL, он всё сохранил, красота.
Теперь как это провернуть на linq? Вижу два варианта.
а) Какие-то динамические запросы... Каждая стратегия вместо того чтобы просто "взять и посчитать" будет куда-то добавлять свою часть запроса. В итоге будет построен какой-то огромный запрос, которые таки да, одной операцией всё пересчитает и обновит. Но зачем эта промежуточная модель? Попробуйте её отладить...
б) Можно апдейтить свойства по одному — одним запросом обновили цену заказа, другим — другое свойство. Будет ли это просто, понятно и эффективно? Тоже сомневаюсь. Какие там ещё проблемы всплывут в конкурентной среде? Теоретически ведь можем в разных запросах использовать одни и те же данные — значит уже нужен repeatable read...