完全に合法的なdbnullに対処するのに苦労しています。モデルデータビューとして渡されているデータセットのデータテーブルを使用します。 ASP.NET MVC2
-
13-10-2019 - |
質問
私はMVCを愛していますが、残念ながらすべてのチュートリアル、デモ、およびすべてのリソースはエンティティフレームワークを使用してViewDataを生成し、ほとんどがデータセットの代わりにSQLを使用しています。
私は既存のビジネスロジックを再利用しており、クライアント(彼自身が優れたコーダーである)は、データセットを使用し続けたいと思っています...だから私はこれらから離れることができません。
データベースでnullにすることができる列を含むテーブルが1つあります。私がこれらにアクセスしようとするとき...それがnullであるかどうかを確認するためでさえ、私は例外を取得します:
「列「FNN_CARRIERS_DESC」の値は表「FNN_CARRIERS_DESC 'IS DBNULL」
これは、dataset.designer.vbファイルによって生成されます。
私はあなたが何を言うつもりか知っています。 「fnn_brandはnull !!!」そして、それは本当です。しかし...このエラーを生成している私のコードのスタックトレースとラインに従ってください。
<%= 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
私が試したこと:
- 例外をコメントすると、それが私が望むものであるものを返しますが、テーブルが変更されたときにデータセットが再構築されます。
- データテーブルの列のルールを変更しました。実際には結果が得られず、テーブル再生でも上書きされます。
- 列が取得されてキャストされているため、ISNothing(列)またはisdbnull(列)は実際にエラーを引き起こします。
うまくいけば、これを解決するための最良の方法を知る必要があります。
仲間のオタクを助けてください...あなたは私の唯一の希望です!
解決 2
誰かが興味を持っているなら、私はより良い解決策を見つけました...中央にレイヤーなしでデータセットを使用し続けることができます。
列はnullableであり、データセットは実際にあなたのための方法を提供します。
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
分かりますか。今ではすべてが清潔でシンプルです。あなたのビューは、強くタイプされた製品オブジェクトで機能し、データセットやデータテーブルや例外を扱うべきではありません。