none
Передать входной параметр хранимой процедуре, сопоставленной с сущностью Entity Framework RRS feed

  • Вопрос

  • При сопоставлении хранимой процедуры сущности Entity Framework, как передать процедуре входной параметр, не являющийся свойством сущности? EF 5 или 6, Database First

    Если это невозможно, какие есть другие пути? Мне нужно, чтобы при каждом изменении моей сущности в EF в клиенте, вызывалась хранимая процедура, которая производила бы это изменение на сервере, притом в эту процедуру нужно передать входной параметр, который не имеет отношения к сущности. (В качестве параметра нужно передать, какой пользователь (оператор базы данных) произвёл это изменение и по просьбе какого клиента (здесь под клиентом подразумеваю человека, которого обслуживает система)).





    26 января 2014 г. 14:19

Все ответы

  • Уточните версиию и модель (Code First или Database First - EDMX).

    Сделаем содержимое сообщества лучше, вместе!

    26 января 2014 г. 15:14
    Модератор
  • EF 5 или 6, Database First
    26 января 2014 г. 15:24
  • Но также интересует и Code First, если знаете :)

    На современных EF — 5 или 6.

    26 января 2014 г. 15:25
  • С версиями всё понятно. Теперь уточните, что значит "При сопоставлении хранимой процедуры сущности Entity Framework" и "Мне нужно, чтобы при каждом изменении моей сущности в EF в клиенте, вызывалась хранимая процедура". Значит ли последнее, что при каждом изменении свойств сущности, должен идти запрос в базу?

    Сделаем содержимое сообщества лучше, вместе!

    26 января 2014 г. 15:32
    Модератор
  • При сопоставлении хранимой процедуры сущности Entity Framework

    Я говорю о сопоставлении хранимых процедур сущностям (изменениям в сущности): Mapping Modification Stored Procedures to Entities, как, например, описано здесь: http://msdn.microsoft.com/en-us/data/gg699321.aspx

    Мне нужно, чтобы при каждом изменении моей сущности в EF в клиенте, вызывалась хранимая процедура

    Да, я планирую сделать что-то вроде этого:

    при каждом изменении свойств сущности, должен идти запрос в базу
    . По крайней мере, я планирую сделать отправку в БД очень частой. Я понимаю, что это отдельная тема, и мой вопрос не об этом. Просто я на всякий случай описал сценарий, в котором у меня возникла необходимость передать входной параметр процедуре — на случай, если от этого сценария зависят пути решения. Возможно, я применяю неправильный подход в программировании всего этого, и, указав сценарий, по которому я работаю, я надеюсь, что опытные участники, возможно, подскажут мне, что мне нужно идти другим путём для достижения моих целей.

    26 января 2014 г. 16:05
  • В ещё более общем обозрении сценарий работы проектируемого приложения таков:

    Назовём человека, который щёлкает кнопочки приложения - оператора базы данных - пользователем. Этот пользователь — служащий. Он обслуживает людей, которых мы назовём клиентами (не путать с клиентом — клиентским приложением, которое, собственно, и проектируется).

    Так вот, к пользователю время от времени обращаются клиенты - подходят к нему лично, и он начинает их обслуживать, используя при этом разрабатываемое приложение.

    Он открывает окошко, в котором отображаются некоторые сведения из БД. Клиент просит пользователя внести некоторые изменения в эти данные. Пользователь их вносит. После внесения приложение должно отправить в БД запрос, в котором будет вызвана хранимая процедура, которая внесёт изменения в БД. При этом хранимой процедуре необходимо передать в качестве двух входных параметров ID этого пользователя, который обслуживал клиента, и ID клиента, который попросил пользователя внести эти изменения. Хранимая процедура не просто вызовет инструкцию UPDATE, в которой произведёт изменение данных, но и запишет в отдельную таблицу (назовём её журналом) какое именно изменение было внесено, каким пользователем и по просьбе какого клиента, а также каково было значение данных до этого изменения, и какое стало после. Такие сведения из журнала в дальнейшем будут использованы другими пользователями для отслеживания изменения данных. Если вдруг другой (или тот же) клиент обратится в систему (к этому же или другому пользователю) с вопросом: «А почему данные имеют такое значение, ведь раньше у них было другое значение?» - то пользователь заглянет в журнал и ответит что-то вроде: «Так ведь такого-то числа во столько-то времени такой-то клиент обратился в систему к такому-то пользователю и попросил его внести эти изменения! А до внесения этих изменений значение данных было такое-то».

    Я решил, что наилучшим решением для реализации такого сценария будет:

    - на стороне сервера - использование хранимой процедуры, которая сначала вызывает инструкцию update и вносит изменения в непосредственно сами данные, а потом записывает все подробности: ID пользователя, клиента, старое и новое значения данных - в таблицу журнала. При этом эта процедура в качестве входящих параметров принимает новые значения данных (старые она и сама может узнать в таблице с данными) и ID пользователя и клиента.

    - на стороне клиентского приложения - использовать Entity Framework, и сопоставить сущности на действие "изменить" указанную хранимую процедуру, а в качестве параметров передать ей новые значения данных и ID пользователя и клиента.

    Правильное ли я принял решение? Как бы Вы это реализовали? Если мой вариант решения логичен, то как же передать входной параметр сопоставленной процедуре?

    26 января 2014 г. 16:21
  • Всё что описали вы, понятно. Есть такая концепция в программировании, называется "Перехват". В частности вам нужно реализовать аудит или говоря по другому "Контроль (Auditing)". Это можно сделать применяя паттерн "Декоратор", в коде, тогда это будет настоящий и правильный ООП подход. А ёщё можете реализовать это на уровне СУБД.

    Сделаем содержимое сообщества лучше, вместе!

    9 февраля 2014 г. 13:30
    Модератор
  • можно сделать применяя паттерн "Декоратор", в коде

    В том-то и дело, что я не хочу, чтобы клиент за этим следил. Я хочу, чтобы этот функционал обеспечивал сервер. Это позволит избежать лишней пересылки данных по сети. И вообще как-то логичнее, по-моему.

    Зачем клиент будет отправлять серверу команды типа: «Измени запись №1: новое значение: "моё новое значение". Потом добавь запись в архив: "Пользователь с кодом 3 внёс в запись 1 изменение "моё новое значение" вместо "моё старое значение"». Как видно, данные передаются дважды, к тому же серверу ещё и передаются старые значения. Зачем их ему передавать, он и сам их знает!

    Если же реализовать это на уровне СУБД, сообщения клиента будут вида: «Измени запись №1: новое значение: "моё новое значение"». А дальше сервер сам запишет в архив всё, что нужно.

    ёщё можете реализовать это на уровне СУБД

    Вот об этом-то и речь. Но вы даёте ссылку на отслеживание измененных данных. В том-то и дело, что эта система отлично подходит для сообщения клиентам обо всём, что изменилось в БД с момента их последнего подключения, но совершенно непригодна для аудита, тем более пользовательского (custom) кастомного. Она позволяет отследить, какие изменения были внесены, но не кем и когда. И она не позволяет производить к информации об изменения фильтрованные SQL-запросы. А это означает, что нельзя будет конечному пользователю предоставить функционал вроде: «как изменялись во времени заказы таким-то клиентом такого-то товара?»

    Именно поэтому я и принял решение реализовать систему «аудита» вручную, на SQL. Проблема лишь в том, что я не могу заставить EF сообщать этой моей системе необходимые для неё сведения непосредственно при изменении данных, то есть в момент изменения сущностей отправлять в хранимые процедуры БД не только сами изменённые сущности, но и ссылки (внешние ключи) на пользователя, внёсшего изменения, и клиента, по чьей инициативе пользователь их внёс. Так-то.

    9 февраля 2014 г. 13:51
  • Кстати.

    ёщё

    «Ёщё»? :) Это что-то новенькое в русском языке! :D

    9 февраля 2014 г. 13:53
  • Прошу прощения. Насчёт того, что Вы предложили только Change Data Capture — это я погорячился. Сейчас внимательнее прочитал ссылку, что Вы дали, и заметил новое для себя средство — Подсистема аудита SQL Server.

    Оно, конечно, может быть более полезно, но всё равно недостаточно. В моём случае необходим именно кастомный аудит, как я понимаю. Например, я хочу отслеживать, в результате каких событий изменялось состояние денежного счёта клиента (человека), например, в результате выполнения его заказа, или в результате пополнения счёта. Отслеживание таких кастомных событий навряд ли сможет выполнить этот компонент (SQL Server Audit). Поэтому я создал таблицу «Операций», в которой есть столбец «тип операции». Вот тип операции может иметь значения «пополнение счёта», «выполнение заказа» и т. д. Соответственно, каждый раз, когда клиент (человек) подходит к пользователю и говорит: «Заказываю такой-то товар в таком-то количестве», то эта команда направляется в СУБД, а там хранимая процедура выполняет примерно следующую последовательность действий: (1) создать событие операцию типа «клиент добавил заказ»; (2) создать в таблице Заказ запись, что такой-то клиент заказал столько-то такого-то товара; (3) изменить в таблице денежных счетов клиентов запись данного клиента, уменьшив её на сумму, равную стоимости его заказа; (4) добавить в журнал запись о том, что заказ такого-то клиента был изменён на столько-то единиц в рамках операции с ID=[код созданной в шаге (1) операции]; (5) добавить в журнал запись о том, что денежный счёт такого-то клиента изменился с такого-то старого значения на такое-то новое в рамках операции с тем же ID.

    Потом можно будет, используя эти данные, предоставить пользователю отчёт типа: «Состояние счёта такого-то клиента в течение запрошенного периода времени менялось следующим образом: (1) в рамках операции "пополнение счёта", произведённой такого-то числа во столько-то времени пользователем таким-то по запросу клиента такого-то, оно изменилось с 100 грн на 150 грн (увеличилось на 50 грн); (2) в рамках операции "заказ товара", произведённой такого-то числа во столько-то времени пользователем таким-то по запросу клиента такого-то, (заказан товар такой-то в количестве таком-то) оно изменилось со 150 грн на 5 грн (уменьшилось на 145 грн)». Как-то так.

    Думаю, такие вещи пока можно реализовать только вручную.





    • Изменено Анатолий A 9 февраля 2014 г. 14:28 !!! Добавил последний абзац!
    9 февраля 2014 г. 14:20
  • Кстати.

    ёщё

    «Ёщё»? :) Это что-то новенькое в русском языке! :D

    С телефона писал, опечаточка вышла. Понимаете задача реализации сложной системы аудита сама по себе непростая, поэтому в подобных случаях мы в наших проектах вообще не используем ORM (хотя если честно, это очень спорный вопрос, в смысле использования EF). А у вас бизнес-логика непростая, нужно время чтобы вникнуть и понять. Времени почти нет в последнее время. В целом, мой совет таков если нужен больший контроль, не используйте ORM. Остальное решать вам.

    Сделаем содержимое сообщества лучше, вместе!

    19 февраля 2014 г. 19:10
    Модератор
  • если нужен больший контроль, не используйте ORM

    Ну да, я, в общем-то, так и подумал. Просто…

    у вас бизнес-логика непростая

    …в том-то и дело, что моя бизнес-логика «зашита» в серверную процедуру. Я от ORM вообще-то и не жду особой гибкости, для неё операции с сущностями будут выполняться прозрачно — лишь бы она могла передать нужный параметр процедуре. А она — блин! — не может! ёпэрэсэтэ!

    19 февраля 2014 г. 19:41