В настоящее время мы используем Entity Framework в качестве ORM для нескольких веб-приложений, и до сих пор она подходила нам, поскольку все наши данные хранятся в одной базе данных. Мы используем шаблон репозитория, и у нас есть службы (уровень домена), которые используют их и возвращают сущности EF непосредственно в контроллеры ASP.NET MVC.
Однако возникло требование использовать сторонний API (через веб-сервис), который даст нам дополнительную информацию, касающуюся пользователя в нашей базе данных. В нашей локальной базе данных пользователей мы будем хранить внешний идентификатор, который мы можем предоставить API для получения дополнительной информации. Доступно довольно мало информации, но для простоты один из них относится к компании пользователя (имя, менеджер, номер, должность, местоположение и т. Д.). Эта информация будет использоваться в разных местах наших веб-приложений, а не в одном месте.
Поэтому мой вопрос: где лучше всего заполнить эту информацию и получить к ней доступ? Так как он используется в разных местах, на самом деле нецелесообразно извлекать его на разовой основе, где бы мы ни использовались в веб-приложении, - поэтому имеет смысл возвращать эти дополнительные данные со слоя домена.
Сначала я хотел создать класс модели-оболочки, который будет содержать сущность EF (EFUser) и новый класс «ApiUser», содержащий новую информацию - и когда мы получим пользователя, мы получим EFUser, а затем получим дополнительный информация из API и заполнить объект ApiUser. Однако, хотя это было бы хорошо для получения отдельных пользователей, оно падает при получении нескольких пользователей. Мы не можем использовать API при получении списка пользователей.
Моей второй мыслью было просто добавить одноэлементный метод к сущности EFUser, который возвращает ApiUser, и просто заполнить его при необходимости. Это решает вышеуказанную проблему, поскольку мы получаем к ней доступ только тогда, когда она нам нужна.
Или последняя мысль заключалась в том, чтобы сохранить локальную копию данных в нашей базе данных и синхронизировать ее с API, когда пользователь входит в систему. Это минимальная работа, так как это всего лишь процесс синхронизации - и у нас нет накладных расходов на попадание БД и API каждый раз, когда мы хотим получить информацию о пользователе. Однако это означает хранение данных в двух местах, а также означает, что данные устарели для любого пользователя, который не вошел в систему в течение некоторого времени.
У кого-нибудь есть какие-либо советы или предложения о том, как лучше всего справиться с таким сценарием?
источник
it's not really sensible to fetch it on an ad-hoc basis
-- Почему? По причинам производительности?Ответы:
Ваш случай
В вашем случае все три варианта являются жизнеспособными. Я думаю, что лучший вариант - это, вероятно, синхронизировать ваши источники данных там, где приложение asp.net даже не знает об этом. То есть избегайте двух выборок на переднем плане каждый раз, синхронизируйте API с БД в режиме без вывода сообщений). Так что, если это приемлемый вариант в вашем случае - я говорю, сделайте это.
Решение, в котором вы делаете выборку «один раз», как предлагает другой ответ, не кажется очень жизнеспособным, поскольку оно нигде не сохраняет ответ, а ASP.NET MVC будет просто делать выборку для каждого запроса снова и снова.
Я бы избегал синглтона, я не думаю, что это хорошая идея по многим обычным причинам.
Если третий вариант не жизнеспособен - один из вариантов являются ленивой загрузкой. То есть, чтобы класс расширял сущность, и чтобы он попадал в API по мере необходимости . Это очень опасная абстракция, так как это еще более волшебное и неочевидное состояние.
Я думаю, это действительно сводится к нескольким вопросам:
Несколько слов о разделении интересов
Позвольте мне поспорить с тем, что Бобсон говорит о разделении проблем здесь. В конце концов - внедрение такой логики в сущности, подобные этим, так же плохо нарушает разделение интересов.
Наличие такого хранилища нарушает разделение проблем так же плохо , помещая логику, ориентированную на представление, на уровень бизнес-логики. Ваш репозиторий теперь внезапно узнает о вещах, связанных с презентацией, например о том, как вы отображаете пользователя в ваших контроллерах asp.net mvc.
В этом связанном вопросе я задал вопрос о доступе к сущностям непосредственно из контроллера. Позвольте мне процитировать один из ответов там:
(Прочитайте остальную часть ответа, это действительно приятно, IMO).
Наивно игнорировать тот факт, что есть база данных - есть база данных, и как бы вы ни старались абстрагироваться, она никуда не денется. Ваша заявка будет знать об источнике данных. Вы не сможете «горячей замены». ORM полезны, но они дают утечку из-за сложности решаемой ими проблемы и из-за множества причин производительности (например, как Select n + 1).
источник
При правильном разделении интересов ничто выше уровня Entity Framework / API не должно даже понимать, откуда поступают данные. Если вызов API не является дорогим (с точки зрения времени или обработки), доступ к данным, которые его используют, должен быть таким же прозрачным, как и доступ к данным из базы данных.
Таким образом, лучший способ реализовать это - добавить дополнительные свойства к
EFUser
объекту, которые по мере необходимости загружают данные API. Что-то вроде этого:Внешне при первом
CompanyName
илиJobTitle
использовании будет выполнен единственный вызов API (и, следовательно, небольшая задержка), но все последующие вызовы, пока объект не будет уничтожен, будут такими же быстрыми и простыми, как и доступ к базе данных.источник
Одна идея состоит в том, чтобы модифицировать ApiUser, чтобы не всегда иметь дополнительную информацию. Вместо этого вы помещаете метод в ApiUser, чтобы получить его:
Вы также можете немного изменить это, чтобы использовать отложенную загрузку дополнительных данных, чтобы вам не нужно было извлекать UserExtraData из объекта ApiUser:
Таким образом, когда у вас есть список, дополнительные данные не будут выбраны по умолчанию. Но вы все равно можете получить к нему доступ, просматривая список!
источник