【问题标题】:Error while trying to exec stored procedure parameters Entity Framework EDMX model in C#尝试在 C# 中执行存储过程参数实体框架 EDMX 模型时出错
【发布时间】:2020-03-03 12:16:05
【问题描述】:

我正在尝试执行我的存储过程,该过程需要 13 个参数,有些可以接受空值,有些始终是必需的。我收到 2 个接受 null 的日期参数的错误。

我收到以下错误

System.Data.SqlClient.SqlException
参数化查询“(@recordType nvarchar(12),@lotCreation bit,@licensePlateCreation”需要参数“@lotManufactureDate”,但未提供。

这是 edmx 模型在我从 SQL Server 数据库调用存储过程时创建的存储过程代码,这里存储过程中名为 licensePlateLookupCode 的参数允许空值,但在 emdx 模型创建的代码中不允许显示它可以取空值 - 你知道为什么吗?

应该是Nullable<string> licensePlateLookupCode,而不是string licensePlateLookupCode

  public virtual int AddFeedbackRequestsAgentInsert(string recordType, 
     Nullable<bool> lotCreation, Nullable<bool> licensePlateCreation, 
     Nullable<int> finishedGoodLineId, Nullable<int> lotid, string 
     lotLookupCode, Nullable<System.DateTime> lotManufactureDate, 
     Nullable<System.DateTime> lotExpirationDate, Nullable<decimal> 
     packagedAmount, Nullable<int> packagingId, string 
     licensePlateLookupCode, Nullable<int> licensePlateId, Nullable<int> 
     licensePlateLocationId)
    {
        var recordTypeParameter = recordType != null ?
            new ObjectParameter("recordType", recordType) :
            new ObjectParameter("recordType", typeof(string));

        var lotCreationParameter = lotCreation.HasValue ?
            new ObjectParameter("lotCreation", lotCreation) :
            new ObjectParameter("lotCreation", typeof(bool));

        var licensePlateCreationParameter = licensePlateCreation.HasValue ?
            new ObjectParameter("licensePlateCreation", licensePlateCreation) :
            new ObjectParameter("licensePlateCreation", typeof(bool));

        var finishedGoodLineIdParameter = finishedGoodLineId.HasValue ?
            new ObjectParameter("finishedGoodLineId", finishedGoodLineId) :
            new ObjectParameter("finishedGoodLineId", typeof(int));

        var lotidParameter = lotid.HasValue ?
            new ObjectParameter("lotid", lotid) :
            new ObjectParameter("lotid", typeof(int));

        var lotLookupCodeParameter = lotLookupCode != null ?
            new ObjectParameter("lotLookupCode", lotLookupCode) :
            new ObjectParameter("lotLookupCode", typeof(string));

        var lotManufactureDateParameter = lotManufactureDate.HasValue ?
            new ObjectParameter("lotManufactureDate", lotManufactureDate) :
            new ObjectParameter("lotManufactureDate", typeof(System.DateTime));

        var lotExpirationDateParameter = lotExpirationDate.HasValue ?
            new ObjectParameter("lotExpirationDate", lotExpirationDate) :
            new ObjectParameter("lotExpirationDate", typeof(System.DateTime));

        var packagedAmountParameter = packagedAmount.HasValue ?
            new ObjectParameter("packagedAmount", packagedAmount) :
            new ObjectParameter("packagedAmount", typeof(decimal));

        var packagingIdParameter = packagingId.HasValue ?
            new ObjectParameter("packagingId", packagingId) :
            new ObjectParameter("packagingId", typeof(int));

        var licensePlateLookupCodeParameter = licensePlateLookupCode != null ?
            new ObjectParameter("licensePlateLookupCode", licensePlateLookupCode) :
            new ObjectParameter("licensePlateLookupCode", typeof(string));

        var licensePlateIdParameter = licensePlateId.HasValue ?
            new ObjectParameter("licensePlateId", licensePlateId) :
            new ObjectParameter("licensePlateId", typeof(int));

        var licensePlateLocationIdParameter = licensePlateLocationId.HasValue ?
            new ObjectParameter("licensePlateLocationId", licensePlateLocationId) :
            new ObjectParameter("licensePlateLocationId", typeof(int));

        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("AddFeedbackRequestsAgentInsert", recordTypeParameter, lotCreationParameter, licensePlateCreationParameter, finishedGoodLineIdParameter, lotidParameter, lotLookupCodeParameter, lotManufactureDateParameter, lotExpirationDateParameter, packagedAmountParameter, packagingIdParameter, licensePlateLookupCodeParameter, licensePlateIdParameter, licensePlateLocationIdParameter);
    }

这是我调用该存储过程的地方,然后在用户单击提交按钮后执行它,我收到 lotmanufacturer 和 lotexpiration 日期参数的错误,因为我认为它们是 NULLS,但在实际的数据库存储过程中它可以取null也可以不取

    private void Btn_Submit_Click(object sender, EventArgs e)
    {
        // db context variable
        var context = _manufacturingDbContext;

        // ** Variables to insert to FootPrint stored procedure datex_footprint_integration.AddFeedbackRequestsAgentInsert with Record Type (FinishedGood)
        const string recordType = "FinishedGood";
        const bool lotCreation = false;
        const bool licensePlateCreation = true;           
        var finishedGoodLineId = context.FinishedGoodLineIdByOrderAndFinishedGoodAndLot(Cmb_MfgOrder.Text, Cmb_FgLookupCode.Text, Cmb_LotLookupCode.Text).FirstOrDefault();         
        var lotId = context.LotIdByManufacturingOrderAndFinishedGood(Cmb_MfgOrder.Text, Cmb_FgLookupCode.Text,Cmb_LotLookupCode.Text).FirstOrDefault();
        var doNotCreateLot = null;
        DateTime? lotManufactureDate = null;
        DateTime? lotExpirationDate = null;
        var packagedAmount = Convert.ToDecimal(Txt_PackagedAmount.Text);
        const int packagedId = 3;
        var licensePlateLookupCode = Txt_LicensePlateLookupCode.Text;
        int? licensePlateId = null;
        const int licensePlateLocationId = 51372;            

        // Call SQL Server SPROC dbo.AddFeedbackRequestsAgentInsert and enter data to FootPrint Task

        context.Database.ExecuteSqlCommand("EXEC dbo.AddFeedbackRequestsAgentInsert " +
                                           "@recordType, @lotCreation, @licensePlateCreation, @finishedGoodLineId, @lotid, @lotLookupCode, @lotManufactureDate," +
                                           "@lotExpirationDate, @packagedAmount, @packagingId, @licensePlateLookupCode, @licensePlateId, @licensePlateLocationId",
                             new SqlParameter("@recordType", recordType),
                                            new SqlParameter("@lotCreation", lotCreation),
                                            new SqlParameter("@licensePlateCreation", licensePlateCreation),
                                            new SqlParameter("@finishedGoodLineId", finishedGoodLineId),
                                            new SqlParameter("@lotid", lotId),
                                            new SqlParameter("@lotLookupCode", doNotCreateLot),
                                            new SqlParameter("@lotManufactureDate", lotManufactureDate),
                                            new SqlParameter("@lotExpirationDate", lotExpirationDate),
                                            new SqlParameter("@packagedAmount", packagedAmount),
                                            new SqlParameter("@packagingId", packagedId),
                                            new SqlParameter("@licensePlateLookupCode", licensePlateLookupCode),
                                            new SqlParameter("@licensePlateId", licensePlateId),
                                            new SqlParameter("@licensePlateLocationId", licensePlateLocationId)
                                            );

        context.SaveChanges();
}

这是实际的存储过程 - 如您所见,@lotManufactureDate@lotExpirationDate 允许空值:

CREATE PROCEDURE [dbo].[AddFeedbackRequestsAgentInsert]
         @recordType NVARCHAR(30),
         @lotCreation BIT,
         @licensePlateCreation BIT,
         @finishedGoodLineId INT,
         @lotid INT NULL,
         @lotLookupCode NVARCHAR(256) NULL,
         @lotManufactureDate DATETIME NULL,
         @lotExpirationDate DATETIME NULL,
         @packagedAmount DECIMAL(28,8),
         @packagingId INT,
         @licensePlateLookupCode NVARCHAR(256) NULL,
         @licensePlateId INT NULL,
         @licensePlateLocationId INT NULL

所以,我不明白为什么当我为那些具有空日期的 2 个日期参数传递时会出现预期的错误查找代码。你能看出这里可能是什么问题吗?

我对我的代码进行了新的更改,现在我没有像我之前的请求描述那样收到错误,但是现在当我调用存储过程来执行时,我在数据库上看不到任何内容,可以在下面查看基于根据 emdx 模型,我提供的参数是否正确?

我从模型浏览器导入函数存储过程调用这个函数,当我点提交按钮时,我没有收到数据库上的任何内容,根据上面的 emdx 模型和存储过程,参数看起来正确吗?

    var context = _manufacturingDbContext;


    const string recordType = "FinishedGood";
    const bool lotCreation = false;
    const bool licensePlateCreation = true;           
    var finishedGoodLineId = context.FinishedGoodLineIdByOrderAndFinishedGoodAndLot(Cmb_MfgOrder.Text, Cmb_FgLookupCode.Text, Cmb_LotLookupCode.Text).FirstOrDefault();         
    var lotId = context.LotIdByManufacturingOrderAndFinishedGood(Cmb_MfgOrder.Text, Cmb_FgLookupCode.Text,Cmb_LotLookupCode.Text).FirstOrDefault();
    var doNotCreateLot = null;
    DateTime? lotManufactureDate = null;
    DateTime? lotExpirationDate = null;
    var packagedAmount = Convert.ToDecimal(Txt_PackagedAmount.Text);
    const int packagedId = 3;
    var licensePlateLookupCode = Txt_LicensePlateLookupCode.Text;
    int? licensePlateId = null;
    const int licensePlateLocationId = 51372;    


        //calling stored procedure and send data to sproc based on the variables above
        context.AddFeedbackRequestsAgentInsert(recordType, lotCreation, licensePlateCreation, finishedGoodLineId,
            lotId, lot, lotManufactureDate, lotExpirationDate, packagedAmount, packagedId, licensePlateLookupCode,
            licensePlateId, licensePlateLocationId);

}

【问题讨论】:

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


    【解决方案1】:

    因此,您更新了数据库中的存储过程,但您的数据模型不知道这些更改..您需要做的是也更新 .net 应用程序中的实体固件.. 1- 刷新(更新)数据库中的 EDMX..

    2- 右键单击​​概念模型 (mode.context.tt) 和 (model.tt),然后单击(运行自定义工具)。这将更新您的 C# 映射数据模型以查看这些添加的新参数。

    【讨论】:

    • 我已经从 edmx 模型中删除了存储过程并重新添加了它,并且刷新了但仍然是这样。我遇到的问题是不允许我为可以采用 NULLS 的参数传递空值,我遇到的空值问题是 lotlookupcode、lotmanufacturerdate、lotexperirationdate。
    • 知道了.. 尽量不要那样执行 Sproc.. 您可以将该 Proc 映射为复杂类型.. 并将其用作 DEF 中的函数..
    • 右键单击您的 EDMX 图表区域,单击模型浏览器右键单击(功能导入并添加您的 Sproc),然后为其命名并将其映射到 EDMX 中的实际 Sproc。 C# 然后这样调用它 using(entities xx = new entity) { xx.function(param1, param2, param3); }
    • 看这个我的朋友:)youtube.com/watch?v=0nYD-_h5Nlk
    • 谢谢你,但是在 C# 代码中调用该函数时,你能用简短的代码显示吗
    【解决方案2】:

    你可以直接调用EF生成的AddFeedbackRequestsAgentInsert方法并传递参数给它。你可能不需要调用ontext.Database.ExecuteSqlCommand

    不过,如果你想使用ontext.Database.ExecuteSqlCommand,你可以使用下面的代码在可为空的日期参数上传递空值

            new SqlParameter("@lotManufactureDate", lotManufactureDate.HasValue ? lotManufactureDate : DBNull.Value),
            new SqlParameter("@lotManufactureDate", lotExpirationDate.HasValue ? lotExpirationDate : DBNull.Value),
    

            new SqlParameter("@lotManufactureDate", lotManufactureDate.HasValue ? lotManufactureDate : default(DateTime)),
            new SqlParameter("@lotManufactureDate", lotExpirationDate.HasValue ? lotExpirationDate : default(DateTime)),
    

    【讨论】:

    • 嘿,伙计,我找到了问题,问题出在数据库存储过程上,这就是错误的原因,但现在我想通过 emdx 模型自动创建的导入函数执行存储过程,但是出于某种原因,我用它运行了我的代码,但我没有向 sproc 发送任何内容,所以问题是我如何执行导入功能?只是通过调用它还是我缺少一个特殊的执行?
    【解决方案3】:

    这是我的答案,我所要做的就是修复我的 sql 存储过程的某些部分,最重要的是,在签入我的数据库数据后,我只需要调用从 emdx 模型创建的导入函数并为其添加正确的参数正在根据代码解决方案正确插入,如果您看到更好的方法,请告诉我。

        public void ExecuteStoredProcedure()
        {
            try
            {
                // db context variable
                var context = _manufacturingDbContext;
    
                const string recordType = "FinishedGood";
                const bool lotCreation = false;
                const bool licensePlateCreation = true;
                var finishedGoodLineId = context.FinishedGoodLineIdByOrderAndFinishedGoodAndLot(Cmb_MfgOrder.Text, Cmb_FgLookupCode.Text, Cmb_LotLookupCode.Text).FirstOrDefault();
                var lotId = context.LotIdByManufacturingOrderAndFinishedGood(Cmb_MfgOrder.Text, Cmb_FgLookupCode.Text, Cmb_LotLookupCode.Text).FirstOrDefault();
                string lot = null;
                DateTime? lotManufactureDate = null;
                DateTime? lotExpirationDate = null;
                var packagedAmount = Convert.ToDecimal(Txt_PackagedAmount.Text);
                const int packagedId = 3;
                var licensePlateLookupCode = Txt_LicensePlateLookupCode.Text;
                int? licensePlateId = null;
                const int licensePlateLocationId = 51372;
    
    
                // Call SQL Server SPROC datex_footprint_integration.AddFeedbackRequestsAgentInsert and enter data to FootPrint Task
                var run = context.AddFeedbackRequestsAgentInsert(recordType, lotCreation, licensePlateCreation, finishedGoodLineId,
                    lotId, "", lotManufactureDate, lotExpirationDate, packagedAmount, packagedId, licensePlateLookupCode,
                    licensePlateId, licensePlateLocationId);
                context.SaveChanges();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                throw;
            }       
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 1970-01-01
      • 2018-07-08
      相关资源
      最近更新 更多