简体   繁体   English

使用Entity Framework从存储过程获取数据

[英]Getting data from stored procedure with Entity Framework

I am trying to get the content a table with a dynamic SQL stored procedure called from the database context object (using Entity Framework 6.1.1), in order to populate a GridView control. 我正在尝试使用从数据库上下文对象(使用Entity Framework 6.1.1)调用的动态SQL存储过程来获取表的内容,以便填充GridView控件。 I fail to retrieve the data. 我无法检索数据。

Here's the stored procedure. 这是存储过程。 It is for a student demonstration about SQL injection in stored procedures, so I KNOW this is inject-able and it's fine. 这是一个有关存储过程中SQL注入的学生演示,所以我知道这是可注入的,也很好。

ALTER PROCEDURE dbo.SearchProducts
  @SearchTerm VARCHAR(max)
AS
BEGIN
  DECLARE @query VARCHAR(max)
  SET @query = 'SELECT * FROM dbo.Products WHERE Name LIKE ''%' + @SearchTerm + '%'''
  EXEC(@query)
END

The C# code behind I then use to execute the stored procedure is : 我随后用来执行存储过程的C#代码是:

var db = new MyEntities();
var TEST_SEARCH_TERM = "product";
var result = db.SearchProducts(TEST_SEARCH_TERM);

MyGridView.DataSource = result;
MyGridView.DataBind();

When executed, in the Database Explorer in Visual Studio, the stored procedure works fine. 在执行时,在Visual Studio的数据库资源管理器中,存储过程可以正常工作。 But when executed in the running ASP.NET app, I get an exception in the DataBind() method because result returns -1 instead of an IEnumerable DataSet containing the objects resulting from the stored procedure's SELECT. 但是,当在运行中的ASP.NET应用程序中执行时,我在DataBind()方法中得到了一个异常,因为result返回-1而不是包含存储过程的SELECT所产生对象的IEnumerable DataSet

How can I retrieve the data and populate my GridView ? 如何检索数据并填充GridView

Use the following steps to solve this issue: 使用以下步骤解决此问题:

  1. You need to Import the stored procedure as a Function. 您需要将存储过程导入为函数。 Right-click on the workspace area of your Entity model and choose Add -> Function Import . 右键单击实体模型的工作区,然后选择Add -> Function Import
  2. In the Add Function Import dialog, enter the name you want your stored procedure to be referred to in your model for example Search_Products , choose your procedure from the drop down list, and choose the return value of the procedure to be Entities and choose Products from the drop down list. 在“添加函数导入”对话框中,输入要在模型中引用存储过程的名称,例如Search_Products ,从下拉列表中选择过程,然后将过程的返回值选择为Entities并从中选择Products 。下拉列表。
  3. Then in the code behind: 然后在后面的代码中:

     var db = new MyEntities(); var TEST_SEARCH_TERM = "product"; var result = db.Search_Products(TEST_SEARCH_TERM);//Search_Products is the name that you specified in Function Import dialog MyGridView.DataSource = result; MyGridView.DataBind(); 

The reason that you get -1 for result is that Entity Framework cannot support Stored Procedure Return values out of the box. 结果为-1的原因是Entity Framework无法直接支持存储过程返回值。 I think support of stored procedure return values depends on version of Entity framework. 我认为对存储过程返回值的支持取决于Entity Framework的版本。 Also Entity Framework doesn't have rich stored procedure support because its an ORM, not a SQL replacement. 另外,Entity Framework不具有丰富的存储过程支持,因为它是ORM而不是SQL的替代品。

I have come across this before with stored procedures using dynamic SQL. 在使用动态SQL的存储过程中,我曾经遇到过这种情况。 I have had success using complex types if I add the line 'SET FMTONLY OFF;' 如果添加“ SET FMTONLY OFF;”行,则我在使用复杂类型方面取得了成功。 (see https://msdn.microsoft.com/en-us/library/ms173839.aspx ) to the top of my stored procedure before it is added to the EF model. (请参阅https://msdn.microsoft.com/zh-cn/library/ms173839.aspx ),然后将其添加到EF模型中。 Once you have your model setup with your complex type, be sure to remove this line. 使用复杂类型设置模型后,请确保删除此行。

Example: 例:

ALTER PROCEDURE dbo.SearchProducts
  @SearchTerm VARCHAR(max)
AS
BEGIN
  SET FMTONLY OFF;
  DECLARE @query VARCHAR(max)
  SET @query = 'SELECT * FROM dbo.Products WHERE Name LIKE ''%' + @SearchTerm + '%'''
  EXEC(@query)
END

Verify that your EDMX has a return type: Go to Function Imports --> SearchProducts, and double click it. 验证您的EDMX是否具有返回类型:转到Function Imports-> SearchProducts,然后双击它。

In order to utilize a Complex return type, Entity Framework will require that you explicitly define column names in your stored procedure instead of using *. 为了利用复杂返回类型,实体框架将要求您在存储过程中显式定义列名,而不是使用*。

Once your stored procedure is modified to define the column names, you can update your model in the project. 一旦修改了存储过程以定义列名,就可以在项目中更新模型。 (Note, performing a complete drop of the SP, and then adding it back to your edmx may be the best route.) (请注意,执行完整的SP删除,然后将其重新添加到edmx可能是最佳途径。)

EDIT 编辑

Maybe you can modify your SP like the following: 也许您可以像下面这样修改您的SP:

ALTER PROCEDURE dbo.SearchProducts
  @SearchTerm VARCHAR(max)
AS
BEGIN
  SELECT * FROM dbo.Products WHERE Name LIKE '%' + @SearchTerm + '%'
END

You seem to have sorted your problem out, there is official documentation from Microsoft available at the links below: 您似乎已经解决了问题,下面的链接提供了Microsoft的官方文档:

How to import a stored procedure into your entity data model: https://msdn.microsoft.com/en-us/library/vstudio/bb896231(v=vs.100).aspx 如何将存储过程导入到实体数据模型: https : //msdn.microsoft.com/zh-cn/library/vstudio/bb896231(v=vs.100).aspx

Complex types in the EF designer: https://msdn.microsoft.com/en-gb/data/jj680147.aspx EF设计器中的复杂类型: https//msdn.microsoft.com/en-gb/data/jj680147.aspx

Make sure you are working with the latest version of .net and you keep your model up to date when you make changes to your database. 确保使用最新版本的.net,并且在更改数据库时保持模型最新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM