Getting stored procedure output parameter with Entity Framework is throwing a mapping error: The data reader is incompatible with the specified
Getting stored procedure output parameter with Entity Framework is throwing a mapping error: The data reader is incompatible with the specified
我正在处理遗留应用程序,我正在尝试调用 returns 一个整数的存储过程,但出现映射错误。错误本身就是这个:
The data reader is incompatible with the specified IF_Insert_Incidents_Citizen'. A member of the type, 'intID', does not have a corresponding column in the data reader with the same name.
我尝试将名称更改为 _intId
,知道 Entity Framework 会将所有以 @variable
开头的名称翻译为 _variable
。
奇怪的是,如果我使用 LinqPad 并调用存储过程,我会得到 @intID
的正确值
这是存储过程:
CREATE PROCEDURE [dbo].[IF_Insert_Incidents_Citizen]
@chvFolio varchar(50),
@chvOwner_Name varchar(100),
@chvOwner_Address varchar(100),
@dtsDate_Created smalldatetime,
@intUser_ID integer,
@chvDescription varchar(250),
@chvEmail varchar(50),
@intIncident_Type_ID integer,
@intIncident_Status integer,
@intID int Output
AS
SET nocount on
DECLARE @intErrorCode INT
DECLARE @intApp_ID INT
SELECT @intIncident_Type_ID = CAST(Param_Value AS INT)
FROM IF_Parameters
WHERE Param_Name = 'Citizen_Incident_Type_ID'
BEGIN
--Get an application id
INSERT INTO MasterApplication (DateCreated)
VALUES (getdate())
SELECT @intApp_ID = SCOPE_IDENTITY()
INSERT INTO IF_Incidents
(
Folio,
Owner_Name,
Owner_Address,
Date_Created,
User_ID,
Description,
Incident_Type_ID,
Incident_Status,
App_ID
)
VALUES
(
@chvFolio,
@chvOwner_Name,
@chvOwner_Address,
@dtsDate_Created,
@intUser_ID,
@chvDescription ,
@intIncident_Type_ID,
@intIncident_Status,
@intApp_ID
)
Select @intErrorCode = @@Error, @intID = SCOPE_IDENTITY()
--Insert Complaint
INSERT INTO IF_Complaints
(
Incident_ID,
Complainant_ID,
Description ,
User_ID,
Officer_Assigned_ID,
Complaint_Status_ID,
Date_Made,
Email_Complainant
)
VALUES
(
@intID,
Null,
@chvDescription + ' at ' + @chvOwner_Address,
1,
1,
1,
@dtsDate_Created ,
@chvEmail
)
Select @intErrorCode = @@Error--, @intID = SCOPE_IDENTITY()
End
Return @intErrorCode
在存储过程中可以看到,intId总是在insert之后得到一个递增的值,调用SCOPE_IDENTITY()
现在我正尝试使用 Entity Framework 以下列方式调用我的存储过程:
var bptRep = DependencyFactory.GetDependency<ICetRepository<IF_Insert_Incidents_Citizen>>();
var parameters = GetIfInsertIncidentsCitizenParamenters();
var res = bptRep.GetAllFromStoredProcedure(storedProcedure, parameters);
存储库使用此 class
//class with just the return value
public class IF_Insert_Incidents_Citizen
{
public int? intID { get; set; }
}
这里我获取了存储过程的所有参数
private IEnumerable<SqlParameter> GetIfInsertIncidentsCitizenParamenters()
{
// Create Parameters
var parameters = new List<SqlParameter>();
var param1 = CreateSqlParameter("@chvFolio", SqlDbType.NVarChar, ParameterDirection.Input, criteria["chvFolio"].Value, 50);
parameters.Add(param1);
....
var paramX = CreateSqlParameter("@intIncident_Status", SqlDbType.Int, ParameterDirection.Input, 10);
parameters.Add(paramX);
var outparam = CreateSqlParameter("@intID", SqlDbType.Int, ParameterDirection.InputOutput, DBNull.Value);
parameters.Add(outparam);
}
public IQueryable<TEntity>GetAllFromStoredProcedure(string storedProcedure, IEnumerable<SqlParameter> parameters)
{
var result = Context.Database.SqlQuery<TEntity>(storedProcedure, parameters).AsQueryable();
return result;
}
我遵循了@GertArnold 建议的方法,但仍然没有用,这是我的参数和代码
var returnCode = new SqlParameter("@ReturnCode", SqlDbType.Int);
returnCode.Direction = ParameterDirection.Output;
var sql = "exec IF_Insert_Incidents_Citizen @chvFolio, @chvOwner_Name, @chvOwner_Address, @dtsDate_Created, @intUser_ID, @chvDescription, @chvEmail, @intIncident_Type_ID, @intIncident_Status, @intID OUT";
var data = ctx.Database.SqlQuery<object>(sql, returnCode, parameters);
var result = data.FirstOrDefault();
最后@GertArnold 给我指明了正确的方向,如果你还没有读过这个post,请读一读,会节省你很多时间Stored procedures with output parameters using SqlQuery in the DbContext API
我刚刚在 exec 调用中将 OUT 添加到我的 @intId 中,无需创建 ReturnCode 变量并调用 exec @ReturnCode = ....
var returnCode = new SqlParameter("@ReturnCode", SqlDbType.Int);
returnCode.Direction = ParameterDirection.Output;
我的代码最终看起来像这样,请注意在参数上调用 .ToArray
方法,而不是将 IEnumerable
或 IList
的集合传递给方法
var sql = "exec IF_Insert_Incidents_Citizen @chvFolio, @chvOwner_Name, @chvOwner_Address, @dtsDate_Created, @intUser_ID, @chvDescription, @chvEmail, @intIncident_Type_ID, @intIncident_Status, @intID OUT";
var data = ctx.Database.SqlQuery<object>(sql, returnCode, parameters.ToArray());
var result = data.FirstOrDefault();
我正在处理遗留应用程序,我正在尝试调用 returns 一个整数的存储过程,但出现映射错误。错误本身就是这个:
The data reader is incompatible with the specified IF_Insert_Incidents_Citizen'. A member of the type, 'intID', does not have a corresponding column in the data reader with the same name.
我尝试将名称更改为 _intId
,知道 Entity Framework 会将所有以 @variable
开头的名称翻译为 _variable
。
奇怪的是,如果我使用 LinqPad 并调用存储过程,我会得到 @intID
这是存储过程:
CREATE PROCEDURE [dbo].[IF_Insert_Incidents_Citizen]
@chvFolio varchar(50),
@chvOwner_Name varchar(100),
@chvOwner_Address varchar(100),
@dtsDate_Created smalldatetime,
@intUser_ID integer,
@chvDescription varchar(250),
@chvEmail varchar(50),
@intIncident_Type_ID integer,
@intIncident_Status integer,
@intID int Output
AS
SET nocount on
DECLARE @intErrorCode INT
DECLARE @intApp_ID INT
SELECT @intIncident_Type_ID = CAST(Param_Value AS INT)
FROM IF_Parameters
WHERE Param_Name = 'Citizen_Incident_Type_ID'
BEGIN
--Get an application id
INSERT INTO MasterApplication (DateCreated)
VALUES (getdate())
SELECT @intApp_ID = SCOPE_IDENTITY()
INSERT INTO IF_Incidents
(
Folio,
Owner_Name,
Owner_Address,
Date_Created,
User_ID,
Description,
Incident_Type_ID,
Incident_Status,
App_ID
)
VALUES
(
@chvFolio,
@chvOwner_Name,
@chvOwner_Address,
@dtsDate_Created,
@intUser_ID,
@chvDescription ,
@intIncident_Type_ID,
@intIncident_Status,
@intApp_ID
)
Select @intErrorCode = @@Error, @intID = SCOPE_IDENTITY()
--Insert Complaint
INSERT INTO IF_Complaints
(
Incident_ID,
Complainant_ID,
Description ,
User_ID,
Officer_Assigned_ID,
Complaint_Status_ID,
Date_Made,
Email_Complainant
)
VALUES
(
@intID,
Null,
@chvDescription + ' at ' + @chvOwner_Address,
1,
1,
1,
@dtsDate_Created ,
@chvEmail
)
Select @intErrorCode = @@Error--, @intID = SCOPE_IDENTITY()
End
Return @intErrorCode
在存储过程中可以看到,intId总是在insert之后得到一个递增的值,调用SCOPE_IDENTITY()
现在我正尝试使用 Entity Framework 以下列方式调用我的存储过程:
var bptRep = DependencyFactory.GetDependency<ICetRepository<IF_Insert_Incidents_Citizen>>();
var parameters = GetIfInsertIncidentsCitizenParamenters();
var res = bptRep.GetAllFromStoredProcedure(storedProcedure, parameters);
存储库使用此 class
//class with just the return value
public class IF_Insert_Incidents_Citizen
{
public int? intID { get; set; }
}
这里我获取了存储过程的所有参数
private IEnumerable<SqlParameter> GetIfInsertIncidentsCitizenParamenters()
{
// Create Parameters
var parameters = new List<SqlParameter>();
var param1 = CreateSqlParameter("@chvFolio", SqlDbType.NVarChar, ParameterDirection.Input, criteria["chvFolio"].Value, 50);
parameters.Add(param1);
....
var paramX = CreateSqlParameter("@intIncident_Status", SqlDbType.Int, ParameterDirection.Input, 10);
parameters.Add(paramX);
var outparam = CreateSqlParameter("@intID", SqlDbType.Int, ParameterDirection.InputOutput, DBNull.Value);
parameters.Add(outparam);
}
public IQueryable<TEntity>GetAllFromStoredProcedure(string storedProcedure, IEnumerable<SqlParameter> parameters)
{
var result = Context.Database.SqlQuery<TEntity>(storedProcedure, parameters).AsQueryable();
return result;
}
我遵循了@GertArnold 建议的方法,但仍然没有用,这是我的参数和代码
var returnCode = new SqlParameter("@ReturnCode", SqlDbType.Int);
returnCode.Direction = ParameterDirection.Output;
var sql = "exec IF_Insert_Incidents_Citizen @chvFolio, @chvOwner_Name, @chvOwner_Address, @dtsDate_Created, @intUser_ID, @chvDescription, @chvEmail, @intIncident_Type_ID, @intIncident_Status, @intID OUT";
var data = ctx.Database.SqlQuery<object>(sql, returnCode, parameters);
var result = data.FirstOrDefault();
最后@GertArnold 给我指明了正确的方向,如果你还没有读过这个post,请读一读,会节省你很多时间Stored procedures with output parameters using SqlQuery in the DbContext API
我刚刚在 exec 调用中将 OUT 添加到我的 @intId 中,无需创建 ReturnCode 变量并调用 exec @ReturnCode = ....
var returnCode = new SqlParameter("@ReturnCode", SqlDbType.Int);
returnCode.Direction = ParameterDirection.Output;
我的代码最终看起来像这样,请注意在参数上调用 .ToArray
方法,而不是将 IEnumerable
或 IList
的集合传递给方法
var sql = "exec IF_Insert_Incidents_Citizen @chvFolio, @chvOwner_Name, @chvOwner_Address, @dtsDate_Created, @intUser_ID, @chvDescription, @chvEmail, @intIncident_Type_ID, @intIncident_Status, @intID OUT";
var data = ctx.Database.SqlQuery<object>(sql, returnCode, parameters.ToArray());
var result = data.FirstOrDefault();