【问题标题】:Stored procedure in Entity Framework database first approach实体框架数据库中的存储过程第一种方法
【发布时间】:2017-05-06 13:29:29
【问题描述】:

我正在使用实体框架数据库优先方法将项目从 Webforms 转换为 MVC 应用程序,并准备好数据库以及所有存储过程。

我成功地创建了一个.edmx 文件并且能够使用我的存储过程,并且当有任何插入或更新操作要执行时它工作得很好。但是当我在我的一个存储过程中使用选择查询时,真正的问题发生了。

例如,有一个Employee 表,它有以下列:

EmpId, FirstName, LastName, Age, Salary

我有一个存储过程GetAllEmpDetails,它有以下选择查询。

Select 
    EmpId, (FirstName + ' ' + LastName) as FullName, Salary 
from 
    Employee

现在,当我尝试将此存储过程的结果与根据表结构具有 5 个属性的 Employee 类绑定时,我收到一个错误,即 Age 属性的值是预期的,但它是在结果集中不可用。

我知道也没有FullName 属性,所以我的问题是如何使用生成的模型类(如本例中的Employee)来解决这个问题,以便它能够处理这些动态?

【问题讨论】:

  • 请贴一些代码
  • @JayakrishnanGounder:实际上这个问题更多是关于方法而不是与实体框架相关的编码问题

标签: c# entity-framework stored-procedures


【解决方案1】:

如何在 EF 中映射存储过程?

由于您正在执行 Database First Approach 并且您有一个 EDMX 文件,因此让 EF 为您生成存储过程结果的类。您可能有许多存储过程,并且希望避免手动创建类:毕竟这就是使用 ORM 工具的全部意义所在。此外,您的一些存储过程可能有参数。按照以下方式进行操作将为您处理所有这些。 其实很简单。

要让 EF 为您执行此操作,请按照以下步骤操作:

  1. 双击您的 EDMX 文件
  2. 选择从数据库更新模型

您将看到类似于以下的对话框:

  1. 确保您已选中如图所示的复选框。

这将添加存储过程,您将在模型浏览器中看到它,如下所示:

  1. 如果您想更改 EF 自动生成的类名,请执行此操作。我强烈建议您这样做,并为您的类指定一个符合 .NET 命名约定的有意义的名称。我遵循的约定是从存储过程名称中删除所有动词并将单词结果附加到末尾。所以你最终会得到如下所示的名称:

  1. 按确定

一些注意事项

这比手动编写类要好得多,以防您的存储过程名称、它需要的参数或它返回的结果发生变化。这种方法也适用于用户定义的函数。

一个陷阱

有时存储过程不会出现在向导对话框的选择中,这是因为this。只需将其添加到存储过程的开头即可:

SET FMTONLY OFF -- REMEMBER to remove it once the wizard is done.

【讨论】:

  • 非常感谢您的回答。我采用了相同的方法,但没有创建新的复杂返回类型,而是选择了实体(在本例中为 Employee),然后在将选择查询与 Employee 映射时产生了问题 类属性。那么如果我想使用EF生成的模型并使用存储过程返回一些东西,那么它应该是相等的,否则它会抛出错误。而且由于我的项目有超过 100 个表,所以我将有额外的 100 个类来处理存储过程。他们不能使用现有模型吗?
  • 为什么要关心班级的数量?它们是由 EF 自动生成的?
  • 如果您的存储过程返回的内容与您的实体之一具有相同的属性,您可以在上图中的第 5 步中选择该实体。
  • 是的,我可以根据我的存储过程创建一个新实体(我们称之为EmployeeOutput)。目前正在使用 Employee 类来完成所有操作,现在在存储过程之后,将有另一个类,它将是 Employee 类的子集,现在我有两个类(具有几乎相同的属性)来处理。之后,对于所有插入和更新操作,将使用 Employee 类,对于选择操作,将使用 EmployeeOutput。所以,我想问一下,是我们在实际应用中如何使用Entity Framework,还是我遗漏了什么?
  • 就像我说的,如果你已经有一个实体,那么将它映射到那个实体。如果您需要一个额外的属性,您可以派生一个类,然后选择它作为存储过程的结果。您可以执行所有这些操作,但只要属性与存储过程中的结果集匹配即可。在上图中的第 5 步中,您可以选择已有的类,EF 会将其映射到该类。有意义吗?
【解决方案2】:
public class EmployeeProcedure
{
    [Column("EmpId")]
    public int EmployeeId { get; set; }

    [NotMapped]
    public string FullName { get; set; }

    public double Salary { get; set; }
}

之后调用这个:

this.Database.SqlQuery<EmployeeProcedure>("GetAllEmpDetails");

【讨论】:

  • 您可能希望在 FullName 上添加一个 [NotMapped] 属性 _ 否则 EF 会尝试从数据库表中获取该属性(它不存在......)
  • 我只是在notepadd++上写的,没有测试,这是解决方法。
猜你喜欢
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-26
相关资源
最近更新 更多