调用Store过程时出错

时间:2018-03-13 16:26:49

标签: c# stored-procedures

我有一个SP,当我从SQL Server Management Studio执行时。但是,当我从我的代码中打电话时:

Database.SqlQuery<Response>("cw.SpGetCompanyLimits @user_id, @company_id",
    new SqlParameter("@user_id", userId),
    new SqlParameter("@company_id", companyId)).Single();

我得到例外:InvalidOperationException: The cast to value type 'System.Decimal' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

我不明白为什么会发生这种情况,因为我的变量是int,并且它们在SP中也定义为int

SP:

CREATE PROCEDURE cw.SpGetCompanyLimits
    @company_id             INT=2,
    @user_id                INT=13
AS BEGIN

DECLARE
@exchange_rate          DECIMAL(19,2),
@dollars_auth_amount    DECIMAL(19,2),
@bols_auth_amount       DECIMAL(19,2),
@auth_limit             DECIMAL(19,2),
@dollars_amount         DECIMAL(19,2),
@bols_amount            DECIMAL(19,2),
@company_limit          DECIMAL(19,2),
@spent_bols             DECIMAL(19,2),
@spent_dollars          DECIMAL(19,2),
@current_date           CHAR(8)

SELECT DISTINCT @auth_limit = Amount FROM Limits WHERE Id = @user_id

SELECT @company_limit = DailyLimit FROM Companies WHERE Id = @company_id

SELECT TOP 1  @exchange_rate = Sale FROM ExchangeRates ORDER BY Date DESC

SET @current_date = CONVERT(CHAR(8), GETDATE(), 112)

SELECT @dollars_amount = COALESCE(SUM(CASE WHEN Currency = 'USD' THEN Amount END), 0.00) ,
   @bols_amount = COALESCE(SUM(CASE WHEN Currency = 'BOL' THEN Amount END), 0.00)          
FROM ProcessBatches
WHERE CompanyId = @company_id AND
  CAST(DateProcess as date) = @current_date AND
  Currency IN ('BOL', 'USD') AND
  OperationTypeId NOT IN (17, 18) AND
  OperationStatusId IN (3, 4, 5, 6);

SELECT @dollars_auth_amount = COALESCE(SUM(CASE WHEN Currency = 'USD' THEN Amount END), 0.00) ,
   @bols_auth_amount = COALESCE(SUM(CASE WHEN Currency = 'BOL' THEN Amount END), 0.00)          
FROM ProcessBatches PB, AuthorizedBatches AB
WHERE CompanyId = @company_id AND
  CAST(DateProcess as date) = @current_date AND
  Currency IN ('BOL', 'USD') AND
  AB.Id = @user_id AND
  OperationTypeId NOT IN (17, 18) AND
  PB.OperationStatusId IN (3, 4, 5, 6);

SELECT 
    @company_limit AS CompanyLimit,
    @auth_limit AS AuthorizerLimit,
CONVERT(DECIMAL(19,2), (@company_limit - (@dollars_amount + @bols_amount / @exchange_rate))) AS Available,
CONVERT(DECIMAL(19,2), (@dollars_amount + @bols_amount / @exchange_rate)) AS SpentMoney,
CONVERT(DECIMAL(19,2), (@dollars_auth_amount + @bols_auth_amount / @exchange_rate)) AS AuthorizedLimit,
@bols_amount AS BolsCompany,
@dollars_amount AS DollarsCompany
END

3 个答案:

答案 0 :(得分:0)

你有两个选择:

在您的Response模型中,将字段类型设为十进制?这样它们就可以为空了。这可能适合您的商业案例,也可能不适合。

或者,确保将查询的null结果设置为默认值,以便它们不会返回为空值。

我个人推荐选项#1。然后,您可以在代码中处理空值,而不是尝试从数据库中操作看似直接的GET。

答案 1 :(得分:0)

我从你的帖子中看到你认为你提供的参数正在抛出异常。可能是返回的数据与您的响应模型不匹配。

您的模型看起来应该是这样的,使用Nullable<decimal>Nullable<float>。附: “回复”不是一个好的类名!

public class Response
{
    public Nullable<decimal> CompanyLimit { get; set; }
    public Nullable<decimal> AuthorizerLimit { get; set; }
    public Nullable<decimal> BolsCompany { get; set; }
    public Nullable<decimal> DollarsCompany { get; set; }
    public Nullable<decimal> Available { get; set; }
    public Nullable<decimal> SpentMoney { get; set; }
    public Nullable<decimal> AuthorizedLimit { get; set; }
}

答案 2 :(得分:0)

我修好了。解决方案很简单。我没有按顺序发送参数,值user_idcompany_id为空(这就是我所理解的)。所以,我改变了这个

Database.SqlQuery<Response>("cw.SpGetCompanyLimits @user_id, @company_id",
    new SqlParameter("@user_id", userId),
    new SqlParameter("@company_id", companyId)).Single();

到这个

Database.SqlQuery<Response>("cw.SpGetCompanyLimits @user_id, @company_id",
    new SqlParameter("@company_id", companyId),
    new SqlParameter("@user_id", userId)).Single();

现在,它有效。我不知道参数的顺序很重要。感谢您的意见。