Возникли проблемы с полностью законным DBNULL. Использование DataSets DataTables, передаваемые как представления данных модели. ASP.NET MVC2
Я люблю MVC, но, к сожалению, все учебники, демонстрации и ВСЕ ресурсы используют Entity Framework для генерации ViewData и большинство используют LINQ to SQL вместо DataSets.
Я повторно использую существующую бизнес-логику, и клиент (который сам по себе является отличным программистом) хочет продолжать использовать наборы данных... поэтому я не могу отойти от них.
У меня есть одна таблица, которая содержит столбцы, которые могут быть NULL в базе данных. Когда я пытаюсь получить доступ к этим... даже для проверки, если это ноль, я получаю исключение:
"Значение для столбца" FNN_CARRIERS_DESC "в таблице" FNN_CARRIERS_DESC "равно DBNull"
Теперь это генерируется файлом dataset.designer.vb.
Я знаю, что ты собираешься сказать. "FNN_BRAND IS НУЛЬ!!!" и это правда. Но... следуйте трассировке стека, и строка в моем коде, которая генерирует эту ошибку, такова:
<%= Html.TextBox("FNN_CARRIERS_DESCTextBox", If(IsNothing(Model.FNN_CARRIERS_DESC), Model.FNN_CARRIERS_DESC, ""))%>
Руководство будет с благодарностью! Моя интуиция говорит мне, что это не просто проблема MVC, но, может быть, я чего-то не понимаю в наборах данных.
Это код в файле reference.vb, который выдает исключение:
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")> _
Public Property FNN_CARRIERS_DESC() As String
Get
Try
Return CType(Me(Me.tableVIT_FNN_CommsService.FNN_CARRIERS_DESCColumn),String)
Catch e As Global.System.InvalidCastException
Throw New Global.System.Data.StrongTypingException("The value for column 'FNN_CARRIERS_DESC' in table 'VIT_FNN_CommsService' is DBNul"& _
"l.", e)
End Try
End Get
Set
Me(Me.tableVIT_FNN_CommsService.FNN_CARRIERS_DESCColumn) = value
End Set
End Property
Вещи, которые я пробовал:
- Если закомментировать исключение, оно вернет значение NULL, чего я и хочу, но набор данных будет перестроен при изменении таблицы или при изменении хранимой процедуры, генерирующей результат таблицы.
- Изменены правила для столбца на DataTable. фактически не дало никакого результата и также будет переопределено при регенерации таблицы.
- IsNothing(столбец) или isDBnull(столбец) на самом деле вызывает ошибку, поскольку столбец извлекается и приводится.
Мне нужно знать лучший способ решить эту проблему, надеюсь, в соответствии с архитектурой MVC.
Помоги мне, ботаны... ты моя единственная надежда!
2 ответа
Если кому-то интересно, я нашел лучшее решение... которое позволит вам продолжать использовать наборы данных без слоя посередине.
Столбец обнуляется, набор данных фактически предоставляет метод для вас.
Model.isFNN_CARRIERS_DESCNull()
так что можно проверить обнуляемость этого столбца... не вызывая сбоя.
Итак, у вас есть логика доступа к данным, основанная на наборах данных. Это прекрасно (подумайте, что могло быть намного хуже, чем в VB6:-)). Нам всем приходится иметь дело с устаревшим кодом. Это нормально. Устаревший код существует везде.
Хотя это не причина загрязнять ваше сверкающее новое приложение MVC этим. Так вот, что я хотел бы предложить вам. Инкапсулируйте этот устаревший код в некоторый внешний репозиторий, который работает только со строгими типами. Пример:
Public Interface IProductsRepository
Function GetProduct(id As Integer) As Product
End Interface
а затем реализовать:
Public Class LegacyProductsRepository
Implements IProductsRepository
Public Function GetProduct(id As Integer) As Product
' TODO: call your legacy code here and convert the datasets
' and datatables you were dealing with into a nice strongly
' typed model object
End Function
End Class
Теперь ваш контроллер никогда не должен слышать о наборах данных и дерьме, как это:
Public Class ProductsController
Inherits Controller
Private ReadOnly _repository As IProductsRepository
Public Sub New(repository As IProductsRepository)
_repository = repository
End Sub
Public Function Show(id As Integer) As ActionResult
Dim product = _repository.GetProduct(id)
Return View(product)
End Function
End Class
Ты видишь. Теперь все чисто и просто. Ваше представление работает со строго типизированным объектом продукта и никогда не должно иметь дело с наборами данных, таблицами данных и исключениями, подобными тому, который вы описываете, никогда не должно происходить:-)