Как заставить проект пользовательского интерфейса многоуровневого решения разрешать объекты EF, не ссылаясь на слой доступа к данным

Я работаю над приложением WinForms, которое состоит из трех слоев, каждый из которых представляет собой отдельный проект, а именно:

Проекты в решении

В проекте SampleNtierDAL есть класс DalServices, который определяется следующим образом:

namespace SampleNtierDAL
{
    public class DalServices
    {
        public static List<Employee> GetEmployees()
        {
            List<Employee> employeeList = null;
            using (SampleNtierEntities aSampleNtierEntitiesDbContext = new SampleNtierEntities())
            {
                employeeList = (from emp in aSampleNtierEntitiesDbContext.Employees select emp).ToList();
            }
            return employeeList;
        }
    }
}

В проекте SampleNtierBLL есть класс BllServices, определенный следующим образом:

namespace SampleNtierBLL
{
    public class BllSerices
    {
        public static List<Employee> GetEmployees()
        {
            return DalServices.GetEmployees();
        }
    }
}

Проект SampleNtierUI имеет событие кнопки WinForm, которое должно запрашивать у BllServices список сотрудников следующим образом:

namespace SampleNtierUI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnGetListOfEmployees_Click(object sender, EventArgs e)
        {
            List<Employee> anEmployeeList = BllSerices.GetEmployees();
        }
    }
}

Проблема здесь в том, что WinForm не может увидеть модель сущности с именем "Employee", которая была создана Entity Frameworks 6. Класс проекта SampleNtierBLL BllServices видит класс, потому что он ссылается на SampleNtierDAL и имеет оператор использования вверху для разрешения Сотрудник класса. Я думал о добавлении аналогичных ссылок в WinForm для разрешения класса Employee, но я видел в других статьях, что вы не должны ссылаться на уровень доступа к данным, но такие статьи не показывают, как решить эту проблему, которая у меня есть.
Может кто-нибудь показать мне, как получить модель Entity (класс Employee), распознаваемый пользовательским интерфейсом (WinForm), не делая ссылки на уровень доступа к данным, где Entity Framework генерирует Entity с именем Employee? Заранее спасибо.

Обновление к моему сообщению 05.11.2015 17:13

После дополнительного тестирования с помощью процедуры, которую я добавил в сообщении 05.11.2015, 15:14, я обнаружил, что он действительно работает и в Visual Studio 2015 с.NET 4.5.2.

Обновление к моему сообщению 05.11.2015 15:14:

Спасибо Реза за всю работу, которую вы вложили в предоставление информации об ответах. Мне не удалось заставить ваше решение работать с Visual Studio 2013 или Visual Studio 2015, поскольку оно задокументировано. Тем не менее, я нашел интернет-видео на Pluralsight.com от Джули Лерман, которое предлагает решение. В ее решении не упоминалось использование части управления NuGet, которую вы сделали, поэтому я добавил ее к миксу и в итоге получил рабочий проект. Видео Джули Лерман озаглавлено:

"Отделение сгенерированных классов доменов от EDMX" и находится здесь:

http://www.pluralsight.com/training/player?course=entity-framework5-getting-started&author=julie-lerman&name=ef5-m6-solutions&clip=2&mode=live

Объединив часть вашей процедуры с ее, я закончил следующими шагами, которые работают для меня в Visual Studio 2013, но не в Visual Studio 2015.

Мой образец изначально имел следующий проект:

  • SampleNtierDAL
  • SampleNtierBLL
  • SampleNtierUI

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

  • SampleNtierDAL
  • SampleNtierBLL
  • SampleNtierUI
  • SampleNtierModels

Шаги для выполнения:1) Настройте ссылки на проект следующим образом:

  1. SampleNtierBLL ссылается на SampleNtierDAL и SampleNtierModels
  2. SampleNtierDAL ссылается на SampleNtierModels
  3. SampleNtierDAL не ссылается на какой-либо проект
  4. SampleNtierUI ссылается на SampleNtierBLL и SampleNtierModels

2) Затем запустите программу "Проводник" (инструмент для просмотра файлов файловой системы) и переместите файл ModelEmployee.tt из папки с файлами проекта DAL в папку с файлами моделей.

3) С помощью обозревателя решений Visual Studio перейдите в проект SampleNtierModels, щелкните правой кнопкой мыши и выберите "Добавить существующий элемент". В диалоговом окне выберите "Все файлы", чтобы увидеть файл ModelEmployee.tt, и выберите его, чтобы добавить его в проект (не выбирайте файл ссылок).

4) Затем выберите проект SampleNtierDAL, затем щелкните правой кнопкой мыши файл ModelEmployee.tt и удалите его, который также автоматически удалит все файлы.cs под ним. Когда это будет сделано, узел ModelEmployee.tt должен исчезнуть.

5) Выберите проект SampleNtierModels, затем щелкните узел ModelEmployee.tt, который откроет файл MoadelEmployee.tt в редакторе. В верхней части содержимого находится константная строка inputFile. Установите эту строку, чтобы найти файл ModelEmployee.edmx следующим образом:

const string inputFile = @"..\SampleNiter\SampleNtierDAL\ModelEmployee.edmx

5) Затем выберите проект SampleNtierDAL, откройте файл ModelEmployee.Context.tt, прокрутите вниз раздел, ссылающийся на предложения, и добавьте пространство имен SampleNtierModels, как показано ниже:

if (container.FunctionImports.Any())
{
#>
using System.Data.Entity.Core.Objects;
using System.Linq;
using SampleNtierModels;
<#
}

7) Выберите проект SampleNtierBLL, откройте файл BLLServices.cs и добавьте следующие операторы using:

using SampleNtierModels;
using SampleNtierDAL;

8) Выберите проект SampleNtierDAL, откройте файл DalServices.cs и добавьте следующий оператор using:

using SampleNtierModels;

7) Выберите проект SampleNtierUI, откройте файл Form1.cs и добавьте следующие операторы using:

using SampleNtierModels;
using SampleNtierBLL

8) Нажмите Инструменты в строке меню, затем Менеджер пакетов NuGet, затем

  1. Выберите установленные пакеты
  2. Поиск Entity Framework
  3. Выберите отображаемый пакет EntityFramework и нажмите кнопку "Управление"
  4. В окне списка убедитесь, что выбраны следующие параметры: SampleNtierBLL, SampleNtierDAL, SamleNtierUI

9) Выберите проект SampleNtierDAL, щелкните правой кнопкой мыши узел ModelEmployee.Context.tt и выберите "Запустить пользовательский инструмент".

10) Выберите проект SampleNtierModels, щелкните правой кнопкой мыши узел ModelEmployee.tt и выберите "Запустить пользовательский инструмент".

11) Скопируйте все содержимое файла App.Config в проекте SampleNtierDAL в файл App.Config проекта SampleNtierUI.

Ниже приведен пример изображения, показывающего, как проект выглядел в конце, а также пример сеанса отладки, показывающий 3 строки данных, возвращаемых из структуры сущностей, которые исходят из DAL, затем в BLL и, наконец, в пользовательский интерфейс. Пользовательский интерфейс Winform также показывает, что ссылка на DAL не нужна.

Эта проблема теперь решена, поэтому еще раз спасибо Реза за помощь в решении этой проблемы. Я оставил сообщение с Juile с просьбой обновить процесс здесь, который включает Visual Studio 2015.

введите описание изображения здесь

1 ответ

Решение

Короткий ответ

Вы должны поместить свои модели в отдельный проект, чем ваш DAL сделать ваши модели видимыми для User Interface (UI) проект без ссылки Data Access Layer (DAL) Проект. И все ваши проекты должны иметь ссылку на ваш проект модели.

Ключевой момент в этом с помощью Database/Model First Подход "Добавить существующий элемент" в ваш проект моделей и выберите .tt файл моделей и выберите Add as Link из раскрывающегося списка кнопки Добавить в диалоговом окне.

Пошаговое руководство по созданию многоуровневого решения

Чтобы поместить ваши модели в отдельный проект с использованием структуры сущности, выполните следующие действия:

Создавать проекты

  1. Создайте проект и назовите его, например Sample.DAL
  2. Создайте другой проект и назовите его Sample.Models
  3. Создайте другой проект и назовите его Sample.BLL
  4. Создайте другой проект и назовите его Sample.UI

Конфигурация Ссылки

Добавьте ссылки на проекты с этими правилами:

  1. Sample.UI зависит от Sample.BLL а также Sample.Models
  2. Sample.BLL зависит от Sample.DAL а также Sample.Models
  3. Sample.DAL зависит от Sample.Models
  4. Sample.Models не зависит от других проектов

Config Sample.DAL

  1. Добавьте свой SampleDB.edmx в Sample.DAL проект
  2. расширять Sample.edmx узел и расширить SampleDB.tt узел и удалите все файлы.cs в SampleDB.tt
  3. В свойствах SampleDB.tt Чисто CustomTool

Config Sample.Models

  1. Add Existing Item в Sample.Models и в диалоговом окне перейдите в папку Sample.DAL и выбрать All files из поля со списком и выберите SampleDB.tt и нажмите на кнопку "Добавить" и в меню выберите Add As Link
  2. выберите SampleDB.tt и в свойствах установите CustomToolNamespace в Sample.DAL
  3. Щелкните правой кнопкой мыши на SampleDB.tt а также Run Custom Tool

Управление пакетами Nuget

  1. Щелкните правой кнопкой мыши по решению и выберите Manage Nuget Packages for Solution и выберите установленные пакеты, выберите Entity Framework и нажмите Управление. выберите Sample.DAL а также Sample.BLL а также Sample.UI

Config Sample.BusinessLogic

Создать YourEntityBusinessLogic класс с этим кодом:

public class YourEntityBusinessLogic
{
    public List<YourEntity> GetAll()
    {
        var context = new YourDBContext();
        return context.YourEntities.ToList();
    }
} 

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

Config Sample.UI

  1. Скопируйте строку подключения из app.config файл из Sample.DAL и вставьте в app.config из Sample.UI до <entityframework> тег.

  2. Создать Form и установите его как запуск и запустить этот код в качестве теста в FormLoad или где вы хотите:

//Shows count of records in your table
var business = new YourEntityBusinessLogic();
MessageBox.Show(business.GetAll().Count().ToString());

Структура решения

Вот структура решения, и, как вы видите, контекст находится в Sample.DAL и модели в Sample.Models,

Так что вам не нужно добавлять ссылку на DAL в вашем UI проект.

Другие вопросы по тегам