Avendo trattare problemi con DBNULL completamente legit. Uso DataSet DataTable vengono passati come dati di viste del modello. ASP.NET MVC2
-
13-10-2019 - |
Domanda
me ne sono innamorato MVC, ma purtroppo tutti i tutorial, demo e tutte le risorse utilizzare Entity Framework per generare Viewdata e la maggior parte l'uso LINQ to SQL, invece di DataSet.
Sto riutilizzando la logica di business esistente e il cliente (che è un grande codificatore in proprio) vuole continuare a utilizzare i set di dati ... quindi non posso spostare lontano da questi.
Ho una tabella che contiene le colonne che sono autorizzati ad essere NULL nel database. Quando provo ad accedere a questi ... anche per verificare se si tratta di nulla ottengo un'eccezione:
"Il valore per la colonna 'FNN_CARRIERS_DESC' nella tabella 'FNN_CARRIERS_DESC' è DBNull"
Ora, questo è generato dal file dataset.designer.vb.
So cosa stai per dire. "FNN_BRAND IS NULL !!!" e questo è vero. Ma ... seguire la traccia dello stack e la linea nel mio codice che genera questo errore è questo:
<%= Html.TextBox("FNN_CARRIERS_DESCTextBox", If(IsNothing(Model.FNN_CARRIERS_DESC), Model.FNN_CARRIERS_DESC, ""))%>
guida sarebbe molto apprezzato! Il mio inutition mi dice che questo non è strettamente un problema di MVC, ma forse qualcosa che non capisco su set di dati.
Questo è il codice nel file Reference.vb che genera l'eccezione:
<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
cose che ho provato:
- Commentando l'eccezione renderà tornare nulla, che è quello che voglio, ma il set di dati verrà ricostruito quando cambia di tabella o la stored procedure che genera il risultato cambia tavolo.
- cambiato le regole per la colonna sulla DataTable. in realtà dato alcun risultato e sarà anche essere sovrascritta sulla rigenerazione tavolo.
- IsNothing (colonna) o IsDBNull (colonna) provoca effettivamente l'errore perché la colonna viene recuperata e colato.
Ho bisogno di sapere il modo migliore per risolvere questo, si spera tenendo con l'architettura MVC.
aiutarmi compagni secchioni ... Sei la mia unica speranza!
Soluzione 2
Se qualcuno è interessato ho trovato una soluzione migliore ... uno che ti permette di mantenere con i set di dati senza strato in mezzo.
Una colonna è annullabile il set di dati in realtà fornisce un metodo per voi.
Model.isFNN_CARRIERS_DESCNull()
in modo si potrebbe verificare l'annullabilità di questa colonna ... senza causare un incidente.
Altri suggerimenti
OK in modo da avere una certa logica di accesso ai dati esistenti che si basa su insiemi di dati. Questo è perfettamente bene (si pensi è che avrebbe potuto essere molto peggio come VB6 :-)). Tutti noi abbiamo a che fare con il codice legacy. È normale. codice legacy esiste ovunque.
Anche se questo non è un motivo per inquinare la nuova applicazione MVC shinning con esso. Quindi, ecco quello che vorrei suggerire. Incapsulare questo codice legacy in qualche repository esterna che funziona solo con tipi forti. Esempio:
Public Interface IProductsRepository
Function GetProduct(id As Integer) As Product
End Interface
e quindi implementare:
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
Ora il controller non dovrebbe mai avere a sentir parlare di set di dati e merda come questo:
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
Si vede. Ora tutto è pulito e semplice. La vista funziona con un oggetto prodotto fortemente tipizzato e non deve mai trattare con serie di dati e DataTable ed eccezioni come quella che si sta descrivendo non dovrebbe mai accadere: -)