【问题标题】:Error on calling stored procedure with output param in Entity Framework code-first在实体框架代码优先中使用输出参数调用存储过程时出错
【发布时间】:2014-03-31 18:41:59
【问题描述】:

从 Entity Framework 调用 ExecuteStoreQuery 时出现以下错误(使用代码优先方法)。

数据读取器有多个字段。多个字段对 EDM 基元或枚举类型无效。

但我的插入/更新操作反映在数据库中。

知道这个问题吗?

这是来自 c# 的代码

long Id=0;

SqlParameter paramoutput = new SqlParameter()
{
   ParameterName = "Result",
   Value = "",
   SqlDbType = System.Data.SqlDbType.BigInt,
   Size = 100,
   Direction = System.Data.ParameterDirection.Output
};

var mydata = (dataContext as IObjectContextAdapter).ObjectContext
             .ExecuteStoreQuery<long>("exec Save @MarkupId, @ApiId, @MainBranchId, @Title, @Markup, @IsPercentage, @IsDomestic, @CreatedOn, @CreatedBy, @ModifiedOn, @ModifiedBy, @IsActive, @Result out",
                 new SqlParameter("@MarkupId", generalMarkupModel.Id),
                 new SqlParameter("@ApiId", generalMarkupModel.ApiId),
                 new SqlParameter("@MainBranchId", generalMarkupModel.MainBranchId),
                 new SqlParameter("@Title", generalMarkupModel.Title),
                 new SqlParameter("@Markup", generalMarkupModel.Markup),
                 new SqlParameter("@IsPercentage", generalMarkupModel.IsPercentage),
                 new SqlParameter("@IsDomestic", generalMarkupModel.IsDomestic),
                 new SqlParameter("@IsActive", generalMarkupModel.IsActive),
                 new SqlParameter("@CreatedOn", DateTime.Now),
                 new SqlParameter("@CreatedBy", "ajc"),
                 new SqlParameter("@ModifiedOn", DateTime.Now),
                 new SqlParameter("@ModifiedBy", "ajm"),
                 paramoutput);

Id = Convert.ToInt64(paramoutput.Value.ToString());
return Id;

存储过程执行insert操作并将@@identity设置为输出参数。

这是我的存储过程:

ALTER PROCEDURE  mypocedurename-here
 @MarkupId bigint,          
 @ApiId int,           
 @MainBranchId int,            
 @Title varchar(50),                    
 @Markup float ,  
 @IsPercentage bit,  
 @IsDomestic bit,
 @CreatedOn datetime, 
 @CreatedBy varchar(50),
 @ModifiedOn datetime, 
 @ModifiedBy varchar(50), 
 @IsActive bit,
 @Result bigint OUTPUT              

AS            
BEGIN            

  INSERT INTO GeneralMarkups            
  ( 
    ApiId,            
   MainBranchId, 
   Title,           
   Markup,            
   IsPercentage ,          
   IsDomestic ,  
   IsActive ,               
   CreatedOn,   
   CreatedBy,  
   ModifiedOn,
   ModifiedBy           
  )            
  VALUES            
  (
    @ApiId,            
   @MainBranchId,            
   @Title,            
   @Markup ,          
   @IsPercentage ,  
   @IsDomestic,
   @IsActive ,          
   @CreatedOn,
   @CreatedBy,  
   @ModifiedOn,
   @ModifiedBy          

  )
  select @Result=@@IDENTITY    

END

【问题讨论】:

  • 邮政编码!我不知道你在说什么。您需要发布给出错误的代码,我们或许可以为您提供帮助。
  • 我们也需要那个存储过程。
  • 我建议使用 SCOPE_IDENTITY() 而不是其他任何东西来获取新插入的标识值。 See this blog post for an explanation as to WHY
  • 这是一个存储过程 - 就像一个procedure,它存储在你的SQL Server中。它不是“store”过程(与“store”无关),也不是“storeprocedure”(这个词在英语中甚至不存在)

标签: c# sql-server entity-framework stored-procedures ef-code-first


【解决方案1】:

首先,您的程序没有选择任何结果。所以你需要选择一些东西(因为你指定了一个long类型的返回结果集)。因此,更改 proc 的最后一行:

-- instead of select @Result=@@IDENTITY 
-- use these lines:
SET @Result = @@IDENTITY
SELECT @Result Result 

现在,您可以通过过程调用获取选定的值。意味着当您执行您的方法时,您将从结果中获得新的 id(作为您的 mydata 参数 - 应该迭代)。

但是仍然有一个错误。你将无法让这条线工作:

Id = Convert.ToInt64(paramoutput.Value.ToString());

因为你的输出参数没有值(它是null),除非你迭代查询的结果。意味着paramoutput.Value 将是null,直到您在查询中调用一个迭代器方法。所以:

SqlParameter paramoutput = new SqlParameter()
{
   ParameterName = "Result",
   // Value = "", no need
   SqlDbType = System.Data.SqlDbType.BigInt,
   // Size = 100, no need
   Direction = System.Data.ParameterDirection.Output
};

var mydata = (dataContext as IObjectContextAdapter).ObjectContext
             .ExecuteStoreQuery<long>("exec Save @MarkupId, @ApiId, @MainBranchId, @Title, @Markup, @IsPercentage, @IsDomestic, @CreatedOn, @CreatedBy, @ModifiedOn, @ModifiedBy, @IsActive, @Result out",
                 new SqlParameter("@MarkupId", generalMarkupModel.Id),
                 new SqlParameter("@ApiId", generalMarkupModel.ApiId),
                 new SqlParameter("@MainBranchId", generalMarkupModel.MainBranchId),
                 new SqlParameter("@Title", generalMarkupModel.Title),
                 new SqlParameter("@Markup", generalMarkupModel.Markup),
                 new SqlParameter("@IsPercentage", generalMarkupModel.IsPercentage),
                 new SqlParameter("@IsDomestic", generalMarkupModel.IsDomestic),
                 new SqlParameter("@IsActive", generalMarkupModel.IsActive),
                 new SqlParameter("@CreatedOn", DateTime.Now),
                 new SqlParameter("@CreatedBy", "ajc"),
                 new SqlParameter("@ModifiedOn", DateTime.Now),
                 new SqlParameter("@ModifiedBy", "ajm"),
                 paramoutput);

// here, the mydata, is of type ObjectResult<long> which you should iterate it to get underlying IDataReader iterated and closed. Then you can use output parameters. So, add this line:
var returnedId = mydata.FirstOrDefault();
// now, the output parameter is available:
Id = Convert.ToInt64(paramoutput.Value.ToString());

请考虑我添加到代码中的 cmets(和新行)。

毕竟,你为什么要传递一个输出参数并选择相同的结果呢?其中一个应该完成工作,另一个是多余的。不是吗?还是有什么我看不到的?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多