#c# #asp.net-mvc #linq #nullable
#c# #asp.net-mvc #linq #обнуляемый
Вопрос:
Я устал исправлять эту ошибку, но ничего не работает.
Вот ошибка:
Система.Исключение InvalidOperationException: объект с нулевым значением должен иметь значение.
в системе.ThrowHelper.Исключение ThrowInvalidOperationException (ресурс ExceptionResource) в системе.Обнуляемый1.get_Value() at
2 параметра) в System.Web.Mvc.ControllerActionInvoker.Метод InvokeActionMethod(ControllerContext ControllerContext, ActionDescriptor actionDescriptor, IDictionary
Finance.Calculator.Presentation.Admin.Areas.HDGS.Controllers.TransactionController.Edit(Int64
TransactionId, String returnURL) in
d:BuildAgent2work83d988abf03ace44CodePresentationFinance.Calculator.Presentation.AdminAreasHDGSControllersTransactionController.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
1 продолжение) в System.Web.Mvc.ControllerActionInvoker.<> c__DisplayClass15.<>c__DisplayClass17.b__14() в System.Web.Mvc.ControllerActionInvoker.invokeactionmethod с фильтрами (ControllerContext ControllerContext, IList
parameters) at
System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter
filter, ActionExecutingContext preContext, Func1 filters, ActionDescriptor actionDescriptor,
2 параметра) в System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext ControllerContext, строковое имя действия)
IDictionary
Вот мой код:
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, но не на серверах, когда он развернут.
Комментарии:
1. в какой строке он выдает ошибку? Просто не бросайте в нас код, попробуйте указать на вещи, которые помогут использовать наше время
2. Какой тип
TransactionItem.IcV
? если онdecimal?
используетсяGetValueOrDefault
вместо приведения (то же самое для всех остальных реквизитов).3. @ Valamas — AUS: Спасибо. Но это отлично работает на моем компьютере разработчика, а не на сервере. Вот почему у меня нет никаких подсказок
4. @ToddWilson: я предполагаю, что причина, по которой вы получаете это только на своем сервере, заключается в том, что переменные там имеют разные значения. Я предполагаю, что у вас есть,
Nullable<T>
которыйnull
. Затем явное преобразование в decimal генерирует исключение.
Ответ №1:
Я предполагаю, что причина, по которой он работает только в вашей среде разработки, заключается в том, что переменные всегда имеют значение там, а на вашем сервере значения с нулевым значением null
.
Если a Nullable<T>
есть null
, вы не можете явно привести его к типу значения, потому что вы получаете исключение «Объект с нулевым значением должен иметь значение». (Демонстрационный вариант)
Поэтому не приводите его. Какое значение вы хотите использовать вместо 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),
Комментарии:
1. Спасибо, Тим. Позвольте мне попробовать это.
2. Привет, Тим. Если вы видите мой код, существует условие, при котором TId не может быть найден в
db.HDGSAccTransaction
В этом случае я показываю сообщение о несуществовании этого TId и ссылку «Вернуться к предыдущему». Даже для этих транзакций я получаю эту ошибку.3. @ToddWilson: я не вижу кода, в котором вы выводите сообщение. Однако я не понимаю, как
if (TransactionItem != null)
это связано с этим. Это просто проверяет,TransactionItem
естьnull
ли это, а не еслиTransactionItem.IcV
естьnull
(или другие обнуляемые свойства).4. @ Tim: Это когда значение null
viewModel object
переходит в view и внутри него я проверяю, является ли model нулевым. Это часть представления. Это просто для того, чтобы вы знали, что я получаю ту же ошибку, даже еслиTransactionItem
равно null5. @ToddWilson: я не настолько знаком с MVC, поэтому я не знаю, что также может вызвать это в этом методе.
TransactionID.Equals
не должен вызывать, даже еслиTransactionID
обнуляемое свойство, которое являетсяnull
.
Ответ №2:
Я только что столкнулся с проблемой симуляции, когда модель базы данных, сгенерированная в entity framework, отличалась от модели домена. Разница заключалась именно в свойстве nullable для целочисленного значения.
Чтобы решить эту проблему, соглашение nullable должно было быть выровнено одинаково как для модели базы данных, так и для модели домена.
Ответ №3:
Я хотел получить обнуляемый тип данных 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>
}
}
Итак, я получил «» для отображаемого значения, если денежная сумма еще не введена.
затем . . . . . при открытии этого для редактирования или добавления значения в классе model.cs я помещаю это выше «AmountAgreedOn»:
[DisplayFormat(ApplyFormatInEditMode = false, DataFormatString = "{0:c}")]
public Nullable<decimal> AmountAgreedOn { get; set; }
Если вы хотите, чтобы отображался знак доллара (не отображался, потому что это мешало сохранению десятичного типа), измените ApplyFormatInEditMode на «true».
Не очень, но я не смог придумать другого способа. Я просто не понимаю, что такое mad scientist.