使用ExecuteSqlCommand调用存储过程(期望未提供的参数)

时间:2015-11-25 10:33:18

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

我尝试使用context.Database.ExecuteSqlCommand从EF调用存储过程,因为我的一个参数是数据表。

以下是程序的参数:

ALTER PROCEDURE [mySchema].[myProc]
    @customerId INT,
    @indicatorTypeId INT,
    @indicators [mySchema].[IndicatorList] READONLY,
    @startDate DATETIME,
    @endDate DATETIME

这是调用存储过程的c#代码:

var indicatorsDt = new DataTable();

indicatorsDt.Columns.Add("Date", typeof(DateTime));
indicatorsDt.Columns.Add("Ongoing", typeof(int));
indicatorsDt.Columns.Add("Success", typeof(int));
indicatorsDt.Columns.Add("Warning", typeof(int));
indicatorsDt.Columns.Add("Error", typeof(int));
indicatorsDt.Columns.Add("Other", typeof(int));

var customerIdParam = new SqlParameter("customerId", SqlDbType.Int);
customerIdParam.Value = customerId;

var typeIdParam = new SqlParameter("indicatorTypeId", SqlDbType.Int);
typeIdParam.Value = typeId;

var startDateParam = new SqlParameter("startDate", SqlDbType.DateTime);
startDateParam.Value = startDate;

var endDateParam = new SqlParameter("endDate", SqlDbType.DateTime);
endDateParam.Value = endDate;

foreach (var indicator in indicators)
{
    indicatorsDt.Rows.Add(indicator.Date, indicator.Ongoing, 
                          indicator.Success, indicator.Warning, 
                          indicator.Error, indicator.Other);
}

var tableParameter = new SqlParameter("indicators", SqlDbType.Structured);
tableParameter.Value = indicatorsDt;
tableParameter.TypeName = "MySchema.IndicatorList";

context.Database.ExecuteSqlCommand("exec MySchema.MyProc", customerIdParam, typeIdParam, tableParameter, startDateParam, endDateParam);

正如您所看到的,提供了所有参数,它们都没有空值,但我总是得到SqlException

  

程序或功能' UpdateIndicators'期望参数   ' @ customerId',未提供。

我无法弄清楚我错过了什么。使用SqlParameter是错误的吗?参数在ExecuteSqlCommand中以相同的顺序提供,即使它不重要。

提前感谢。

5 个答案:

答案 0 :(得分:0)

试试这个:

var customerIdParam = new SqlParameter("@customerId", SqlDbType.Int);

答案 1 :(得分:0)

以下是我目前使用参数调用存储过程的方法。用您自己的参数名称/值替换参数名称/值。请记住,您可能必须按照存储过程中声明的顺序列出参数。

创建一个SqlParameter数组:

SqlParameter[] parameters = new SqlParameter[] {
     new SqlParameter("@ParamName1", Value1),
     new SqlParameter("@ParamName2", Value2),
     new SqlParameter("@ParamName3", Value3),
     new SqlParameter("@ParamName4", Value4),
     new SqlParameter("@ParamName5", Value5)
};

然后调用您的存储过程:

 _context.Database.ExecuteSqlCommand(DbHelper.GenerateCommandText("SpName", parameters), parameters);

这是DbHelper代码:

public class DbHelper
{
    public static string GenerateCommandText(string storedProcedure, SqlParameter[] parameters)
    {
        string CommandText = "EXEC {0} {1}";
        string[] ParameterNames = new string[parameters.Length];

        for (int i = 0; i < parameters.Length; i++)
        {
            ParameterNames[i] = parameters[i].ParameterName;
        }

        return string.Format(CommandText, storedProcedure, string.Join(",", ParameterNames));
    }
}

答案 2 :(得分:0)

这有效:

var bookIdParameter = new SqlParameter();
bookIdParameter.ParameterName = "@BookId";
bookIdParameter.Direction = ParameterDirection.Output;
bookIdParameter.SqlDbType = SqlDbType.Int;
var authors = context.Database.ExecuteSqlCommand("usp_CreateBook @BookName, @ISBN, @BookId OUT",
    new SqlParameter("@BookName", "Book"),
    new SqlParameter("@ISBN", "ISBN"),
    bookIdParameter);

答案 3 :(得分:0)

存储库

 public  async Task<int> ExecuteStoredProcedure(string sqlQuery,int user_id, T entity, params object[] parameters)
    {
       const int ENTITY_ID_INDEX = 19;
       var result= _context.Database.ExecuteSqlCommand(sqlQuery, parameters);
       var history = _context.History.AddAsync(new History { CreatedDate = DateTime.Now, EventId = Events.CREATE_EVENT_ID, ObjectId =Convert.ToInt32(((SqlParameter) parameters[ENTITY_ID_INDEX]).Value), ObjectStr = JsonConvert.SerializeObject(entity), ObjectName = entity.GetType().Name, UserId = user_id });
       _context.SaveChanges();
       return result; 
    }

存储过程

ALTER PROCEDURE [dbo].[spInboxDocumentAdd]
@DocumentTypeId int,
@DocumentKindId int,
@DocumentKindCode nvarchar(50),
@RegistrationDate datetime,
@ApplicantId int,
@ApplicantAddress nvarchar(255),
@ApplicantFullName nvarchar(255),
@DocumentDate datetime,
@DocumentNumber nvarchar(255),
@IsForInformation bit,
@IsForControl bit,
@DeadlineDate datetime,
@ReminderDate datetime,
@SummaryId int,
@UserId int,
@Note nvarchar(255),
@Mail nvarchar(255),
@Account nvarchar(10),
@RegistrationNumber nvarchar(50) Output,
@CurrentId int

AS
Declare @OrderNumber int,@CreatedDate datetime, @RegistrationNumberIn nvarchar(50), @Deleted bit

SET @CreatedDate=SYSDATETIME();
SET @OrderNumber=ISNULL((SELECT MAX(OrderNumber)+1 FROM dbo.InboxDocuments WHERE DocumentKindId=@DocumentKindId AND YEAR(CreatedDate)=YEAR(@CreatedDate)),0);
IF (@OrderNumber IS NULL)
BEGIN
SET @OrderNumber=0;
END
SET @RegistrationNumberIn=CONVERT(nvarchar(50),@DocumentKindCode+'/'+CONVERT(nvarchar(50),@OrderNumber)+'-'+CONVERT(nvarchar(50),YEAR(@CreatedDate)));
SET @Deleted=0;

INSERT INTO [dbo].[InboxDocuments]
           ([DocumentTypeId]
           ,[DocumentKindId]
           ,[OrderNumber]
           ,[RegistrationDate]
           ,[RegistrationNumber]
           ,[CreatedDate]
           ,[ApplicantId]
           ,[ApplicantAddress]
           ,[ApplicantFullName]
           ,[DocumentDate]
           ,[DocumentNumber]
           ,[IsForInformation]
           ,[IsForControl]
           ,[DeadlineDate]
           ,[ReminderDate]
           ,[SummaryId]
           ,[Deleted]
           ,[UserId]
           ,[Note]
           ,[Mail]
           ,[Account])
     VALUES
           (
           @DocumentTypeId,
           @DocumentKindId,
           @OrderNumber,
           @RegistrationDate,
           @RegistrationNumberIn,
           @CreatedDate,
           @ApplicantId,
           @ApplicantAddress,
           @ApplicantFullName,
           @DocumentDate,
           @DocumentNumber,
           @IsForInformation,
           @IsForControl,
           @DeadlineDate,
           @ReminderDate,
           @SummaryId,
           @Deleted,
           @UserId,
           @Note,
           @Mail,
           @Account
           );

SET @CurrentId= @@IDENTITY;
SET @RegistrationNumber=@RegistrationNumberIn;
SELECT @RegistrationNumber;
RETURN @CurrentId;

控制器

private string CreateInboxDocument(InboxDocuments inboxDocument, string documentKindCode, int user_id)
    {
        const int REGISTRATION_DATE_INDEX = 18;
        const int ENTITY_ID = 19;
        SqlParameter DocumentTypeId = new SqlParameter();
        DocumentTypeId.ParameterName = "@DocumentTypeId";
        DocumentTypeId.SqlDbType = SqlDbType.Int;
        DocumentTypeId.Direction = ParameterDirection.Input;
        DocumentTypeId.Value = inboxDocument.DocumentTypeId;

        SqlParameter DocumentKindId = new SqlParameter();
        DocumentKindId.ParameterName = "@DocumentKindId";
        DocumentKindId.SqlDbType = SqlDbType.Int;
        DocumentKindId.Direction = ParameterDirection.Input;
        DocumentKindId.Value = inboxDocument.DocumentKindId;

        SqlParameter DocumentKindCode = new SqlParameter();
        DocumentKindCode.ParameterName = "@DocumentKindCode";
        DocumentKindCode.SqlDbType = SqlDbType.VarChar;
        DocumentKindCode.Size = 50;
        DocumentKindCode.Direction = ParameterDirection.Input;
        DocumentKindCode.Value = documentKindCode;

        SqlParameter RegistrationDate = new SqlParameter();
        RegistrationDate.ParameterName = "@RegistrationDate";
        RegistrationDate.SqlDbType = SqlDbType.DateTime;
        RegistrationDate.Direction = ParameterDirection.Input;
        RegistrationDate.Value = inboxDocument.RegistrationDate;

        SqlParameter ApplicantId = new SqlParameter();
        ApplicantId.ParameterName = "@ApplicantId";
        ApplicantId.SqlDbType = SqlDbType.Int;
        ApplicantId.Direction = ParameterDirection.Input;
        ApplicantId.Value = inboxDocument.ApplicantId;

        SqlParameter ApplicantAddress = new SqlParameter();
        ApplicantAddress.ParameterName = "@ApplicantAddress";
        ApplicantAddress.SqlDbType = SqlDbType.VarChar;
        ApplicantAddress.Size = 50;
        ApplicantAddress.Direction = ParameterDirection.Input;
        ApplicantAddress.Value = documentKindCode;

        SqlParameter ApplicantFullName = new SqlParameter();
        ApplicantFullName.ParameterName = "@ApplicantFullName";
        ApplicantFullName.SqlDbType = SqlDbType.VarChar;
        ApplicantFullName.Size = 50;
        ApplicantFullName.Direction = ParameterDirection.Input;
        ApplicantFullName.Value = documentKindCode;

        SqlParameter DocumentDate = new SqlParameter();
        DocumentDate.ParameterName = "@DocumentDate";
        DocumentDate.SqlDbType = SqlDbType.DateTime;
        DocumentDate.Direction = ParameterDirection.Input;
        DocumentDate.Value = inboxDocument.RegistrationDate;

        SqlParameter IsForInformation = new SqlParameter();
        IsForInformation.ParameterName = "@IsForInformation";
        IsForInformation.SqlDbType = SqlDbType.Bit;
        IsForInformation.Direction = ParameterDirection.Input;
        IsForInformation.Value = inboxDocument.IsForInformation;

        SqlParameter IsForControl = new SqlParameter();
        IsForControl.ParameterName = "@IsForControl";
        IsForControl.SqlDbType = SqlDbType.Bit;
        IsForControl.Direction = ParameterDirection.Input;
        IsForControl.Value = inboxDocument.IsForControl;

        SqlParameter DeadlineDate = new SqlParameter();
        DeadlineDate.ParameterName = "@DeadlineDate";
        DeadlineDate.SqlDbType = SqlDbType.DateTime;
        DeadlineDate.Direction = ParameterDirection.Input;
        DeadlineDate.Value = inboxDocument.DeadlineDate;

        SqlParameter ReminderDate = new SqlParameter();
        ReminderDate.ParameterName = "@ReminderDate";
        ReminderDate.SqlDbType = SqlDbType.DateTime;
        ReminderDate.Direction = ParameterDirection.Input;
        ReminderDate.Value = inboxDocument.RegistrationDate;

        SqlParameter UserId = new SqlParameter();
        UserId.ParameterName = "@UserId";
        UserId.SqlDbType = SqlDbType.Int;
        UserId.Direction = ParameterDirection.Input;
        UserId.Value = inboxDocument.UserId;

        SqlParameter Note = new SqlParameter();
        Note.ParameterName = "@Note";
        Note.SqlDbType = SqlDbType.VarChar;
        Note.Size = 255;
        Note.Direction = ParameterDirection.Input;
        Note.Value = inboxDocument.Note;


        SqlParameter Mail = new SqlParameter();
        Mail.ParameterName = "@Mail";
        Mail.SqlDbType = SqlDbType.VarChar;
        Mail.Size = 255;
        Mail.Direction = ParameterDirection.Input;
        Mail.Value = inboxDocument.Mail;

        SqlParameter Account = new SqlParameter();
        Account.ParameterName = "@Account";
        Account.SqlDbType = SqlDbType.VarChar;
        Account.Size = 255;
        Account.Direction = ParameterDirection.Input;
        Account.Value = inboxDocument.Account;

        SqlParameter CurrentId = new SqlParameter();
        CurrentId.ParameterName = "@CurrentId";
        CurrentId.SqlDbType = SqlDbType.Int;
        CurrentId.Direction = ParameterDirection.Output;
        CurrentId.Value = 0;

        SqlParameter DocumentNumber = new SqlParameter();
        DocumentNumber.ParameterName = "@DocumentNumber";
        DocumentNumber.SqlDbType = SqlDbType.VarChar;
        DocumentNumber.Size = 50;
        DocumentNumber.Direction = ParameterDirection.Output;
        DocumentNumber.Value = inboxDocument.DocumentNumber;


        SqlParameter RegistrationNumber = new SqlParameter();
        RegistrationNumber.ParameterName = "@RegistrationNumber";
        RegistrationNumber.SqlDbType = SqlDbType.VarChar;
        RegistrationNumber.Size = 50;
        RegistrationNumber.Direction = ParameterDirection.Output;
        RegistrationNumber.Value = "";

        SqlParameter SummaryId = new SqlParameter();
        SummaryId.ParameterName = "@SummaryId";
        SummaryId.SqlDbType = SqlDbType.Int;
        SummaryId.Direction = ParameterDirection.Input;
        SummaryId.Value = inboxDocument.SummaryId;

        using (var unitOfWork = new UnitOfWork(new DbContext.ApplicationDbContext(workflow_optionsBuilder.Options)))
        {
            SqlParameter[] @params = new SqlParameter[] { DocumentTypeId, DocumentKindId, DocumentKindCode, RegistrationDate, ApplicantId, ApplicantAddress, ApplicantFullName, DocumentDate, DocumentNumber, IsForInformation, IsForControl, DeadlineDate, ReminderDate, SummaryId, UserId, Note, Mail, Account, RegistrationNumber, CurrentId  };
            var row_affected = unitOfWork.InboxDocuments.ExecuteStoredProcedure("exec @CurrentId=spInboxDocumentAdd @DocumentTypeId, @DocumentKindId, @DocumentKindCode, @RegistrationDate, @ApplicantId, @ApplicantAddress, @ApplicantFullName, @DocumentDate, @DocumentNumber, @IsForInformation, @IsForControl, @DeadlineDate, @ReminderDate,@SummaryId, @UserId, @Note, @Mail, @Account,@RegistrationNumber OUTPUT, @CurrentId", user_id, inboxDocument, @params);
            CurrentDocumentId = Convert.ToInt32(@params[ENTITY_ID].Value);
            return @params[REGISTRATION_DATE_INDEX].Value.ToString();
        }
    }

答案 4 :(得分:-2)

您缺少正在执行的SQL字符串中的参数。尝试使用&#34; @&#34;创建参数。在名称前面,然后将ExecuteSqlCommand调用更改为:

context.Database.ExecuteSqlCommand("exec MySchema.MyProc @customerId, @indicatorTypeId, @indicators, @startDate, @endDate", customerIdParam, typeIdParam, tableParameter, startDateParam, endDateParam);