Использование Entity Framework для возврата таблицы данных для итерации

В настоящее время я использую EF 6, чтобы сделать следующее. Выполните хранимую процедуру, затем введите данные, которые мне нужно использовать. Данные обычно представляют собой 30-40 строк за один запуск приложения.

Затем я перебираю переменную, объект, таблицу (как бы вы это ни называли), выполняя аналогичные (иногда разные) задачи для каждой строки. Это прекрасно работает. Я могу создать объект Entity, раскрыть его различные сложные функции, а затем создать переменную для повторения.

Нравиться:

foreach (var result in StoredProcedureResult)
{
string strFirstname = result.FirstName
string strLastName = result.LastName
//more logic goes here using those variables and interacting with another app

}

Недавно я подумал, что было бы круто, если бы у меня был класс исключительно для доступа к данным. Таким образом, я мог бы просто сослаться на этот класс, добавить соответствующую строку подключения в свой app.config, а затем я мог бы разделить два набора логики. Поэтому, пытаясь сделать вышеописанное в этой структуре, я дохожу до точки, в которой вы не можете вернуть var или когда я пытаюсь сопоставить тип возвращаемого объекта. Тип возвращаемого значения выполнения хранимой процедуры - объект (который я не могу повторять).

Итак, мой вопрос: как добраться до приведенного выше примера, за исключением того, что результат var возвращается из этого класса доступа к данным?

Если я что-то упускаю или это невозможно, потому что я делаю это неправильно, дайте мне знать. Оно возникло прямо у меня в голове.


person MZawg    schedule 07.12.2018    source источник
comment
вы смотрели на импорт функций в EF?   -  person Marty    schedule 07.12.2018
comment
@Марти, эй, спасибо за ответ. У меня сложилось впечатление, что я уже использовал импорт функций? Разве это не результат приведенного выше фрагмента кода? StoredProcedureResult был выполнен следующим образом: EntityName db = new EntityName(); var StoredProcedureResult = db.Sp_That_Returns_SomeRows_And_Columns(); db.Dispose();   -  person MZawg    schedule 07.12.2018
comment
во-первых: если EntityName является именем класса вашего DbContext, то более обычным способом будет использование using вместо Dispose см. документ. во-вторых: импорт функции должен позволить вам указать, что процедура возвращает сложный тип, таким образом, вы получите этот тип, возвращенный вместо объекта   -  person Marty    schedule 07.12.2018
comment
@Marty, хорошо, понял, оберну это в using.hmm, похоже, что в раскрывающемся списке он установлен как сложный. Таким образом, полный тип VS вызывает его: System.Data.Entity.Core.Objects.ObjectResult   -  person MZawg    schedule 10.12.2018
comment
@Marty, так что все в порядке, вышеизложенное, похоже, решило проблему с типом возвращаемого значения, а ObjectResult - это тип возвращаемого значения, который вы можете перебирать. Еще одна небольшая проблема. Так вот в моем посте с примером возврата имени или фамилии видно, что создаются get и set для конкретных столбцов, а в DataAccessLayer я вижу эти методы. Проблема в том, что в проекте, ссылающемся на DAL, string strFirstname = result.FirstName нет intellisense, показывающего список столбцов при вводе result., поэтому я думаю, что здесь что-то упускаю.   -  person MZawg    schedule 10.12.2018
comment
@Marty продвинулся немного дальше, вы можете сделать ObjectResult<NameOfYourFunction_Result) это правильный тип возврата, и это работает. Моя проблема в том, что я использовал идею, которую мне дал ответ другого человека на Stack. Приложение -- Уровень доступа к данным -- Общий уровень, каждый из которых является отдельным проектом, и у меня сложилось впечатление, что я могу содержать все свои материалы для доступа к данным в одном месте, а затем поделиться ими с общим уровнем, а затем сделать ссылку из основного приложения в общий проект, и это откроет доступ к методам общего проекта, вызывающим уровень доступа к данным.   -  person MZawg    schedule 10.12.2018
comment
Проблема в том, что все проверяется, за исключением того, что основной проект приложения хочет, чтобы я сделал ссылку на уровень доступа к данным. Однако моя цель состояла в том, чтобы не делать ссылку на этот проект, а вместо этого сделать ссылку на общий слой.   -  person MZawg    schedule 10.12.2018


Ответы (1)


Я не буду описывать архитектуру полностью. Но, основываясь на ваших комментариях, вы можете сделать следующее (это не окончательный и не единственный способ сделать это):

  1. в вашем проекте доступа к данным вы сохраняете класс DBContext, весь код для вызова хранимой процедуры, а также класс, определяющий результат вызова SP, назовем его классом A;
  2. в вашем проекте общего слоя - я бы предложил назвать его сервисным слоем - вы можете создать класс XYService, который имеет метод, например. GetListOfX, который подключается к БД и вызывает процедуру, при необходимости этот метод также может выполнять некоторую логику, но что более важно: он возвращает не класс A, а возвращает новый класс B (этот определен на сервисном уровне, или может быть определен в еще одном проекте - это может быть настоящий общий/общий проект; поскольку это будет просто определение общих структур, это не совсем слой);
  3. на уровне приложения вы работаете только с методом GetListOfX XYService и класса B, поэтому вам не нужна ссылка на проект доступа к данным

В тривиальном случае класс B имеет те же свойства, что и класс A. Но в зависимости от ваших потребностей класс B может иметь дополнительные свойства/функциональность, он также может игнорировать некоторые свойства A или даже объединять несколько свойств в одно: например. объединение FirstName и LastName в одно свойство, называемое просто Name.

В основном то, что вы ищете, - это многоуровневая архитектура приложения (обычно 3-4 уровня). Полная степень такого подхода (который включает интенсивное использование таких концепций, как интерфейсы и внедрение зависимостей) может не подходить или не требоваться в зависимости от ваших целей, например. если вы строите для себя просто маленькое приложение с парой функций или знаете, что повторного использования компонентов конечного решения не будет, то такой подход слишком расточительный и можно быстрее работать со всем в одном проекте - вам по-прежнему следует применять такие принципы, как SOLID, DRY и Разделение опасения.

person Marty    schedule 10.12.2018
comment
Реализовал это решение. Благодаря вашим ссылкам для чтения и отличному объяснению, я думаю, что теперь начал делать приличное многоуровневое приложение. Это было не столько «должен ли я это делать», сколько «могу ли я». С этой помощью я смог. Спасибо, Марти! - person MZawg; 11.12.2018
comment
Я думаю, что единственное место, где я мог отклониться от вашего направления, было на первом шаге. Уровень My Data больше похож на сервисный класс только с методами, которые используют EF для вызова SP, а затем возвращают результат. Я думаю, что это немного отличается от того, когда вы сказали: весь код для вызова хранимой процедуры, а также класс, который определяет результат вызова SP - person MZawg; 11.12.2018
comment
@MikeCMR существует несколько способов использования EF, в простых случаях вам даже не нужны SP и вы можете запрашивать таблицы с помощью LINQ, если вы еще не смотрели на это, я бы посоветовал вам прочитать об этом;) - person Marty; 11.12.2018