系统无效操作异常:可空对象必须具有值。ASP.NET MVC

6

我已经厌倦了修复这个错误,但什么都不起作用。

以下是错误信息:

System.InvalidOperationException: 可空对象必须有一个值。
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Nullable1.get_Value() at Finance.Calculator.Presentation.Admin.Areas.HDGS.Controllers.TransactionController.Edit(Int64 TransactionId, String returnURL) in d:\BuildAgent2\work\83d988abf03ace44\Code\Presentation\Finance.Calculator.Presentation.Admin\Areas\HDGS\Controllers\TransactionController.cs:line 44 at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.b__14() at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

以下是我的代码:

public ViewResult Edit(string TId, string returnURL)
    {
        long tid = !string.IsNullOrEmpty(TId) ? Convert.ToInt64(TId) : Convert.ToInt64(Request.QueryString["TId"].ToString());
        var TransactionItem = db.HDGSAccTransaction.SingleOrDefault(t => t.TransactionID.Equals(tid));
        TransactionVM oTrns = null;
        if (!string.IsNullOrEmpty(returnURL))
        {
            TempData["ReturnUrl"] = returnURL;
        }
        if (TransactionItem != null)
        {
            oTrns = new TransactionVM
            {
                TRef = TransactionItem.dimTransaction.TRef,
                Yr = TransactionItem.Yr,
                IcV = (decimal)TransactionItem.IcV,
                OFv = (decimal)TransactionItem.OFv,
                OCBv = (decimal)TransactionItem.OCBv,
                OOBv = (decimal)TransactionItem.OOBv,
                OInv = (decimal)TransactionItem.OInv
            };
        }

        return View(oTrns);
    }

请注意:这个代码在Visual Studio的开发环境中运行良好,但是在部署到服务器上时却无法正常运行。

2
它在哪一行出错了?不要只是把代码扔给我们,尝试指出一些东西来帮助利用我们的时间。 - Valamas
TransactionItem.IcV的类型是什么?如果是decimal?,则使用GetValueOrDefault而不是强制转换(对于所有其他属性也是如此)。 - Alessandro D'Andria
@ Valamas - AUS:谢谢。但是这在我的开发机上运行良好,在服务器上却不行。这就是为什么我没有任何提示的原因。 - Todd Wilson
1
@ToddWilson:我猜你只在你的服务器上遇到这个问题是因为变量在那里有不同的值。我假设你有一个Nullable<T>,它是null。然后显式转换为十进制会抛出异常。 - Tim Schmelter
3个回答

10
我猜测它只在你的开发环境中工作是因为变量总是有值的,而在服务器上,可空变量是null
如果Nullable<T>null,则无法将其显式转换为值类型,因为会出现异常"Nullable object must have a value"。(演示
所以不要进行强制转换。你想使用什么值来代替null,你可以使用decimal.MinValue
// ...
IcV = TransactionItem.IcV.HasValue ? TransactionItem.IcV.Value : decimal.MinValue,
// ...

如果有用的话,这里是一个扩展方法:

public static T SafeCast<T>(this Nullable<T> t, T defaultValue = default(T)) where T : struct
{
    return t.HasValue ? t.Value : defaultValue;
}

从现在开始你可以使用这个:

IcV = TransactionItem.IcV.SafeCast(decimal.MinValue),

谢谢Tim。让我试试这个。 - Todd Wilson
嗨,Tim。如果你看到我的代码,有一个条件是在db.HDGSAccTransaction中找不到TId。在这种情况下,我会显示一个关于该TId不存在的消息和“返回上一页”的链接。即使对于那些交易,我也会遇到这个错误。 - Todd Wilson
@ Tim:这是当空的“viewModel对象”进入视图并在其中检查模型是否为空时发生的。这是视图部分。这只是让您知道,即使“TransactionItem”为空,我仍然会收到相同的错误。 - Todd Wilson
我猜它只在你的开发环境中工作的原因是变量总是有值,而在你的服务器上,可空变量为空。是的,你是对的。但为什么呢? - Chinh Phan
很棒的解释和演示链接。非常有用。 - GlennG
显示剩余2条评论

0
我想让可空的SQL Server Money数据类型以只读方式显示为2位小数: 我使用传入的模型(c.AmountAgreedOn),并在视图中的td行内放置了以下内容:
   @{
    string value = "";
    decimal? decimalValue = c.AmountAgreedOn;
    if (decimalValue.HasValue)
    {
         value = ((decimal)(decimalValue)).ToString("0.00");
        <td align="center">@value</td>
    }
    else
    {
               <td align="center">@value</td>
    }
}

如果未输入金额,则我会为显示值获取“”。

然后……打开模型.cs类以编辑或添加值时,我会将其放在“AmountAgreedOn”之上:

[DisplayFormat(ApplyFormatInEditMode = false, DataFormatString = "{0:c}")]
public Nullable<decimal> AmountAgreedOn { get; set; }

如果你想要美元符号显示出来(因为它会影响保存小数类型),请将ApplyFormatInEditMode更改为“true”。

虽然不太美观,但我找不到其他方法。我就是不懂那些疯狂科学家的东西。


0

我刚刚遇到了一个类似的问题,即使用实体框架生成的数据库模型与领域模型不同。差异主要在于整数值的可空属性。

为了解决这个问题,必须使可空约定在数据库模型和领域模型中保持一致。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接