Как получить доступ к свойствам класса EF из сервисного уровня

У меня есть ASP.NET MVC3 на С# и Razor. Архитектура приложения разделена на уровень доступа к данным (классы EF + репозиторий), уровень обслуживания, контроллер, модели представления и представление.

Из моего уровня обслуживания ProductServices я вызываю метод GetAllProducts, предоставленный моим репозиторием ProductRepository, который имеет следующую подпись:

IQueryable<Products> GetAllProducts()

Поэтому внутри ProductServices я вызываю (productRepository является экземпляром ProductRepository):

var products = productRepository.GetAllProducts(); 

который заполняет переменную products. Теперь я хотел бы получить доступ к названию продукта ProductName из productServices. Если я использую эту инструкцию:

var productNames = products.Select(m => m.ProductName).ToList();

Я создаю связь между ServiceLayer и EF (в обход репозитория). Это означает, что я должен добавить в ProductRepository метод с сигнатурой:

IQueryable<string> GetAllProductsName()

Однако, поскольку мне нужна другая информация о продукте в моем приложении, должен ли я создать один метод в productRepository для каждого поля класса Product? Верны ли мои рассуждения? Спасибо


person CiccioMiami    schedule 20.02.2012    source источник
comment
Зачем вам нужен сервисный уровень, если он просто проксирует запросы?   -  person Eranga    schedule 20.02.2012
comment
спасибо за Ваш ответ. Конечно, у меня также есть вся бизнес-логика и несколько методов на моем сервисном уровне, поэтому мне это нужно.   -  person CiccioMiami    schedule 20.02.2012
comment
Что заставляет вас думать, что этот тип связи плохой?   -  person Eranga    schedule 20.02.2012
comment
Потому что я заранее знаю, что через год база данных будет заменена другой. Это означает, что имя полей, скорее всего, будет изменено, и я также должен изменить их в своем репозитории и, в случае сопряжения, также на моем сервисном уровне.   -  person CiccioMiami    schedule 20.02.2012


Ответы (2)


Есть две школы мысли по этому поводу,

  1. Репозиторий явно определяет способ взаимодействия с базой данных и должен строго контролироваться. Поэтому методы репозитория должны предоставлять перечисляемые данные.
  2. Репозиторий разрывает сильную связь с конкретным типом источника данных, но ему не нужно предоставлять подробные и пронумерованные наборы данных.

Лично я подписываюсь на второй, вот почему:

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

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

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

Если вам интересно, вот мой взгляд на репозитории: http://blog.staticvoid.co.nz/2011/10/staticvoid-repository-pattern-nuget.html, весь код тоже на github

person Not loved    schedule 20.02.2012
comment
спасибо за Ваш ответ. Поэтому вы предлагаете мне не создавать специальные методы и обращаться к полю через сервисный уровень, минуя репозиторий? - person CiccioMiami; 20.02.2012
comment
Я чувствую, что, обращаясь к queriable напрямую, вы на самом деле не обходите репозиторий, вы как бы делаете расширение времени выполнения. так что да, я был бы в порядке, используя выбор после того, как вы вернете набор из репозитория. Здесь также важно отметить, что выбор на самом деле является функцией LINQ, а не EF или вашего репозитория, и он вполне успешно будет работать и с перечисляемым набором. - person Not loved; 20.02.2012
comment
а если я заранее узнаю, что БД (и соответственно EF) будет заменена? Если я получаю доступ к полям только из productRepository, мне нужно изменить только этот слой - person CiccioMiami; 20.02.2012
comment
да, конечно, изменение слоя не должно быть проблемой, единственная проблема заключается в том, что если новая ORM, которую вы используете, не поддерживает компиляцию linq в SQL, ваш метод репозитория может работать немного медленнее, поскольку запрос будет извлекать больше материала. - person Not loved; 20.02.2012

У вас есть вся информация в вашем productServices, потому что вы загружаете всю информацию из своего репозитория с помощью метода productRepository.GetAllProducts(). Если вам нужна дополнительная информация от другого объекта, вам необходимо расширить свои productServices с помощью новой службы.

Однако, поскольку мне нужна другая информация о продукте в моем приложении, должен ли я создать один метод в productRepository для каждого поля класса Product? Верны ли мои рассуждения? Спасибо

В этой ситуации обычно я создаю методы Extensions для службы, а не в репозитории. В репозитории обычно есть установка CRUD и ничего более.

person theforce    schedule 20.02.2012
comment
спасибо, это означает, что вы получаете доступ к полям непосредственно на сервисном уровне, верно? Конечно, у меня есть и другие методы, кроме GetAllProducts, я не перечисляю их здесь, потому что они не рассматриваются. - person CiccioMiami; 20.02.2012
comment
В этом случае да. Никогда нет, если вам нужна эта логика в другом приложении или контексте базы данных (например, приложение WPF или мобильное приложение). С вашей сервисной архитектурой вы можете хорошо справиться с этой ситуацией. - person theforce; 20.02.2012