使用带有 C# 的 Entity Framework 6 调用现有的存储过程
Posted
技术标签:
【中文标题】使用带有 C# 的 Entity Framework 6 调用现有的存储过程【英文标题】:Calling existing Stored procedure using Entity Framework 6 with C# 【发布时间】:2017-07-26 16:38:43 【问题描述】:我需要知道如何使用c#
调用实体框架6 Code First中的现有存储过程。
以下是我正在使用的程序:
CREATE PROCEDURE proc_getEmployees
@departmentname varchar(50),
@sortCol varchar(30),
@sortdir varchar(25),
@searchString varchar(50)
AS
BEGIN
SET NOCOUNT ON;
declare @strSQl varchar(1000);
declare @strSQlwhere varchar(500);
declare @strSelectEndPart varchar(100);
set @strSQl = ';WITH employeetable as
(
select ROW_NUMBER() OVER (ORDER BY '+@sortCol+' '+@sortdir+' ) AS RowNumber,COUNT(*) over() as TotalRecords, ID,FirstName,LastName,Designation,DepartmentName,Contact,EmailAddress,Location from Employees ';
set @strSQlwhere = 'where DepartmentName = '''+@departmentname+'''';
set @strSQlwhere = @strSQlwhere+ ' and (Id like ''%' + @searchString + '%'' Or FirstName like ''%' + @searchString + '%'' Or LastName like ''%' + @searchString + '%'' Or Designation like ''%' + @searchString + '%'' Or DepartmentName like ''%' + @searchString + '%'' Or Contact like ''%' + @searchString + '%'' Or EmailAddress like ''%' + @searchString + '%'' Or Location like ''%' + @searchString + '%'')';
set @strSelectEndPart =') select * from employeetable';
set @strSQl = @strSQl +@strSQlwhere+@strSelectEndPart;
execute (@strSQl);
END
GO
我正在查询的表是员工,其结构如下:
Column Type Length
ID int 4
FirstName varchar 50
LastName varchar 50
Designation varchar 50
DepartmentName varchar 50
Contact varchar 50
EmailAddress varchar 50
Location varchar 50
DBContext 类如下:
public class DevelopmentTestDatabaseContext :DbContext
public DevelopmentTestDatabaseContext() : base("name =DevelopmentTestDatabaseContext")
public virtual DbSet<Employee> EmployeeData get; set;
存储过程调用方法如下:
public void GetEmployeeDataUsingProcedure()
object[] parameters = new SqlParameter[4];
List<EmployeeResultSet> lstEmployees = new List<EmployeeResultSet>();
try
using (var db = new DevelopmentTestDatabaseContext())
SqlParameter param = new SqlParameter("@departmentname", "IT");
parameters[0] = param;
param = new SqlParameter("@sortCol", "ID");
parameters[1] = param;
param = new SqlParameter("@sortdir", "asc");
parameters[2] = param;
param = new SqlParameter("@searchString", "ope");
parameters[3] = param;
var results = db.Database.SqlQuery<EmployeeResultSet>("proc_getEmployees @departmentname, @sortCol, @sortdir, @searchString", parameters);
db.Database.Log = query => System.Diagnostics.Debug.Write(query);
lstEmployees = results.ToList();
catch (Exception ex)
为存储过程结果集定义了如下类:
public class EmployeeResultSet
public int rowNumber get; set;
public int totalRecords get; set;
public int ID get; set;
public string FirstName get; set;
public string LastName get; set;
public string Designation get; set;
public string DepartmentName get; set;
public string Contact get; set;
public string EmailAddress get; set;
public string Location get; set;
请让我知道在调用存储过程之前是否需要做任何其他事情。我是 EF6 的新手,遇到了问题。代码中缺少什么?我需要对任何课程进行一些更改吗?
【问题讨论】:
如果我没记错的话,你所有的参数都是new SqlParameter("@searchString", "ope")
。你应该做parameters[0] = new SqlParameter("@key", "value"); parameters[1] = new SqlParameter("@key2", "value2");
等等。本质上你是在说parameters[0]-[4] = param
。然后你改变它每一行。因此,您正在更改数组中的值。
【参考方案1】:
我可以说的一个问题是在您调用该过程的方法中。您将数组的所有元素设置为等于param
,但您不断更改param
。您的所有元素都将等于param
的最终状态。试试这个:
public void GetEmployeeDataUsingProcedure()
object[] parameters = new SqlParameter[4];
List<EmployeeResultSet> lstEmployees = new List<EmployeeResultSet>();
try
using (var db = new DevelopmentTestDatabaseContext())
parameters[0] = new SqlParameter("@departmentname", "IT");
parameters[1] = new SqlParameter("@sortCol", "ID");
parameters[2] = new SqlParameter("@sortdir", "asc");
parameters[3] = new SqlParameter("@searchString", "ope");
var results = db.Database.SqlQuery<EmployeeResultSet>("proc_getEmployees @departmentname, @sortCol, @sortdir, @searchString", parameters);
db.Database.Log = query => System.Diagnostics.Debug.Write(query);
lstEmployees = results.ToList();
catch (Exception ex)
//log it or something
可能还有其他问题,但无需过多研究,我需要有关您遇到的特定错误或行为的更多信息。
您也可以尝试输入数据库的全名:
"MyDatabase.MySchema.proc_getEmployees @departmentname, @sortCol, @sortdir, @searchString"
编辑根据您的 cmets:
快速闪避,我找到了this。从本质上讲,如果您在查询中将您的号码转换为int
,您应该没问题。所以而不是:
select * from employeetable
试试:
select CAST(RowNumber as int) as RowNumber,
CAST(TotalRecords as int) as TotalRecords,
CAST(ID as int) as ID,
FirstName,
LastName,
Designation,
DepartmentName,
Contact,
EmailAddress,
Location
from employeetable
【讨论】:
感谢您提供详细信息,尝试了提到的参数选项,得到错误为从具体化的“System.Int64”类型到“System.Int32”类型的指定转换无效。另外,当我尝试记录查询时 嗯,也许可以尝试将您的课程int
s 更改为 long
s,请参阅此处:***.com/questions/3845205/how-to-use-int64-in-c-sharp 和此处:***.com/questions/32264382/…
仍然出现同样的错误。还有一件事要澄清,就像在我调用存储过程的语句中一样,
仍然出现同样的错误。还有一件事要澄清,因为我在代码中调用过程时使用 EmployeeResultSet 是否需要在 DevelopmentTestDatabaseContext 类中定义,因为我只有一个属性,即这个 public virtual DbSet顺便说一句,但您实际上没有必要使用动态 SQL。特别是当搜索条件是字符串时,坚持参数化查询更安全。在您的情况下,您可以执行以下操作:
;WITH employeetable as
(
select
CASE WHEN @sortDir = 'asc' THEN
ROW_NUMBER() OVER (ORDER BY
CASE WHEN @sortCol = 'ID' THEN ID END,
CASE WHEN @sortCol = 'FirstName' THEN FirstName END,
CASE WHEN @sortCol = 'LastName' THEN LastName END,
CASE WHEN @sortCol = 'Designation' THEN Designation END,
CASE WHEN @sortCol = 'DepartmentName' THEN DepartmentName END,
CASE WHEN @sortCol = 'Contact' THEN Contact END,
CASE WHEN @sortCol = 'EmailAddress' THEN EmailAddress END,
CASE WHEN @sortCol = 'Location' THEN Location END
ASC) ELSE ROW_NUMBER() OVER (ORDER BY
CASE WHEN @sortCol = 'ID' THEN ID END,
CASE WHEN @sortCol = 'FirstName' THEN FirstName END,
CASE WHEN @sortCol = 'LastName' THEN LastName END,
CASE WHEN @sortCol = 'Designation' THEN Designation END,
CASE WHEN @sortCol = 'DepartmentName' THEN DepartmentName END,
CASE WHEN @sortCol = 'Contact' THEN Contact END,
CASE WHEN @sortCol = 'EmailAddress' THEN EmailAddress END,
CASE WHEN @sortCol = 'Location' THEN Location END
DESC) END AS RowNumber,
COUNT(*) over() as TotalRecords, ID,FirstName,LastName,Designation,
DepartmentName,Contact,EmailAddress,Location from Employees
where DepartmentName = @departmentname and
(Id like '%' + @searchString + '%' Or FirstName like '%'
+ @searchString + '%' Or LastName like '%' + @searchString + '%'
Or Designation like '%' + @searchString + '%' Or
DepartmentName like '%' + @searchString + '%' Or
Contact like '%' + @searchString + '%' Or
EmailAddress like '%' + @searchString + '%' Or
Location like '%' + @searchString + '%')
)
select * from employeetable
【讨论】:
感谢您的输入将进行这些更改,但我的问题是为什么我在调用存储过程时出现错误,过程在 sql server 中运行良好 我得到的错误是从物化的“System.Int64”类型到“System.Int32”类型的指定转换无效。也尝试更改该类的数据类型,但仍然没有运气以上是关于使用带有 C# 的 Entity Framework 6 调用现有的存储过程的主要内容,如果未能解决你的问题,请参考以下文章
带有 Entity Framework Core 的 SQLite 很慢
如何使用 C# 将 Include 动态添加到 ObjectSet<Entity>?
c# Enumerable中Aggregate和Join的使用
如何在 ASP.NET MVC 5、Entity Framework 6 中使用流利的 API 映射表?