如何在不引用数据访问层的情况下使分层解决方案的 UI 项目解析 EF 实体

How do you make a layered solution's UI project resolve EF Entities without referencing the data access layer

我正在开发一个 WinForms 应用程序,我将其分为 3 层,每层一个单独的项目,如下所示:

SampleNtierDAL 项目中有一个 DalServices class,其定义如下:

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 class 定义如下:

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

Te 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 无法看到由 Entity Frameworks 创建的名为 "Employee" 的实体模型 6. SampleNtierBLL 项目 class BllServices 看到 class 因为它引用了 SampleNtierDAL 并且在顶部有一个 use 语句来解析 Employee class。我考虑过在 WinForm 中添加类似的引用来解决 Employee class 但我在其他文章中看到你不应该引用数据访问层但是这些文章没有说明如何解决这个问题我有。
有人可以告诉我如何获得 UI (WinForm) 识别的实体模型 (Employee class),而不引用 Entity Framework 生成名为 Employee 的实体的数据访问层? 提前致谢。

更新到我的 post 11/5/2015 5:13 PM

在对 post 11/5/2015 3:14 PM 添加的程序进行更多测试后,我发现它实际上也适用于 Visual Studio 2015 和 .NET 4.5 .2.

更新到我的 post 11/5/2015 3:14 pm:

感谢 Reza 为提供回复信息所做的所有工作。我无法使您的解决方案与记录的 Visual Studio 2013 或 Visual Studio 2015 一起使用。但是,我确实在 Julie Lerman 的 Pluralsight.com 上找到了一个提供解决方案的互联网视频。她的解决方案没有提到使用您所做的 NuGet 管理部分,所以我将其添加到组合中并最终得到了一个工作项目。 Julie Lerman 的视频标题为:

"Separating Generated Domain Classes from 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 年无效。

我的示例最初有以下项目:

在这个项目列表中,我添加了第四个名为 SampleNtierModels 的项目,因此现在的列表如下:

要遵循的步骤: 1) 设置项目引用如下:

  1. SampleNtierBLL 引用 SampleNtierDAL 和 SampleNtierModels
  2. SampleNtierDAL 引用 SampleNtierModels
  3. SampleNtierDAL 没有引用任何项目
  4. SampleNtierUI 引用 SampleNtierBLL 和 SampleNtierModels

2) 接下来,启动文件资源管理器程序(用于浏览文件系统文件的工具)并将ModelEmployee.tt文件从DAL项目文件夹移动到模型文件夹。

3) 使用 Visual Studio 解决方案资源管理器,转到 SampleNtierModels 项目,右键单击并 select 添加现有项。在对话框中,select "All Files" 以查看 ModelEmployee.tt 文件,select 将其添加到项目中(不要选择 link 文件)。

4) 接下来,select SampleNtierDAL 项目,然后右键单击ModelEmployee.tt 文件并将其删除,这也会自动删除其下的所有.cs 文件。完成后 ModelEmployee.tt 节点应该消失了。

5) Select SampleNtierModels 项目然后单击 ModelEmployee.tt 节点,这将在编辑器中打开 MoadelEmployee.tt 文件。内容的顶部是对常量字符串 inputFile 的赋值。设置此字符串以定位 ModelEmployee.edmx 文件,如下所示:

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

5) 接下来,select SampleNtierDAL 项目并打开 ModelEmployee.Context.tt 文件并向下滚动引用 using 子句的部分并添加 SampleNtierModels 名称 space,如下所示:

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

7) SelectSampleNtierBLL工程,打开BLLServices.cs文件,添加如下using语句:

using SampleNtierModels;
using SampleNtierDAL;

8) SelectSampleNtierDAL工程,打开DalServices.cs文件,添加如下using语句:

using SampleNtierModels;

7) SelectSampleNtierUI工程,打开Form1.cs文件,添加如下using语句:

using SampleNtierModels;
using SampleNtierBLL

8) 单击菜单栏中的工具,然后单击 NuGet 包管理器,然后

  1. Select 已安装的软件包
  2. 搜索 Entity Framework
  3. Select 显示的 EntityFramework 包然后点击它 "Manage" 按钮
  4. 确保在列表框中 select 编辑了以下内容: SampleNtierBLL、SampleNtierDAL、SamleNtierUI

9) Select SampleNtierDAL项目,右键单击 ModelEmployee.Context.tt 节点和 select "Run Custom Tool".

10) Select SampleNtierModels 项目,右键单击 ModelEmployee.tt 节点和 select "Run Custom Tool".

11) 将SampleNtierDAL项目中App.Config文件的全部内容复制到SampleNtierUI项目的App.Config文件中。

下面是一个示例图片,显示了项目最终的样子,以及一个示例调试 session,显示了从 entity framework 返回的 3 行数据,这些数据源自 DAL,然后到BLL,最后是 UI。 Winform UI 也显示不需要对 DAL 的引用。

此问题现已解决,再次感谢 Reza 帮助解决此问题。我已经给 Juile 留言,要求更新这里的流程,其中包括 Visual Studio 2015.

简答

您应该将您的模型放在与您的 DAL 不同的项目中,以使您的模型对 User Interface (UI) 项目可见,而无需引用 Data Access Layer (DAL) 项目。你所有的项目都应该引用你的模型项目。

使用 Database/Model First 方法执行此操作的关键点是 "Add Existing Item" 您的模型项目和 select .tt 模型文件并选择 Add as Link来自对话框中“添加”按钮的下拉菜单。

创建分层解决方案的分步指南

要使用 entity framework 将您的模型放入单独的项目中,请遵循以下步骤:

创建项目

  1. 创建一个项目并命名例如Sample.DAL
  2. 创建另一个项目并将其命名为Sample.Models
  3. 创建另一个项目并将其命名为Sample.BLL
  4. 创建另一个项目并将其命名为 Sample.UI

配置参考

添加对具有这些规则的项目的引用:

  1. Sample.UI 依赖于 Sample.BLLSample.Models
  2. Sample.BLL 依赖于 Sample.DALSample.Models
  3. Sample.DAL 依赖于 Sample.Models
  4. Sample.Models 对其他项目没有依赖性

配置Sample.DAL

  1. 将您的 SampleDB.edmx 添加到 Sample.DAL 项目
  2. 展开Sample.edmx节点,展开SampleDB.tt节点,删除SampleDB.tt
  3. 下的所有.cs文件
  4. SampleDB.tt 的属性中清除 CustomTool

配置Sample.Models

  1. Add Existing ItemSample.Models 并在对话框中,转到 Sample.DAL 的文件夹并从组合框中选择 All files 和 select SampleDB.tt 并单击“添加”按钮的下拉菜单,然后从菜单中选择 Add As Link
  2. 选择SampleDB.tt,在属性中,将CustomToolNamespace设置为Sample.DAL
  3. 右键单击 SampleDB.ttRun Custom Tool

管理 Nuget 包

  1. 右键单击解决方案和 select Manage Nuget Packages for Solution 和 select 安装包,select Entity Framework 然后单击管理。选择 Sample.DALSample.BLLSample.UI

配置Sample.BusinessLogic

使用以下代码创建 YourEntityBusinessLogic class:

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

注意不要在 public 属性中或作为方法和构造函数的输入参数或作为 return 值公开 YourDBContext。

配置Sample.UI

  1. Sample.DALapp.config 文件中复制您的连接字符串并粘贴到 Sample.UIapp.config 标签之前 <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 中。

因此您不需要在 UI 项目中添加对 DAL 的引用。