Entity Framework 5 と Database First (SQL Server 2008 R2 への接続) を使用して VB.NET 11 WPF MVVM アプリケーションを作成しようとしています。
もちろん、データベースが既に存在する WPF MVVM に既存のソリューションを移行しているため、データベース ファーストを選択しました。
できるだけ多くのコードを単体テストできるように、依存性注入の使用を開始したいと考えています。
EF DB-First、特にvb.netで依存性注入を使用する方法の明確で簡潔なウォークスルーを見つけることができないようです。C# の例でも問題ありませんが、私は確信しています。
私が本当に欲しいのは、ソリューションをセットアップする方法、依存性注入の準備ができている各部分をセットアップする方法などを説明する簡単なステップバイステップのガイドですが、これらを手に入れるのは難しいようです.
これまでのところ、次のようにソリューションとプロジェクトを作成しました。
- DBAccess - これには、私の .edmx ファイルと、コンストラクターに ConnectionString を提供できるようにするための小さな mod しか含まれていません。
- DBControl - これには、EDMX と ViewModel の間のレイヤーを提供するために使用するさまざまなクラスが含まれています。具体的には、UI を介して「より使いやすい」データを表示し、保存/更新のためにこれらの「使いやすい」複合型をマップされたエンティティに変換するために、ここで複合型 (デザイナーを使用して作成したもの) を埋めています。データベースのテーブルごとに 1 つのクラスがあります。それぞれに 2 つの"FetchFriendlyRecords"メソッド (1 つはフィルターを受け入れます) と " AddUpdateFriendlyRecord " メソッドがあります。各クラスのインターフェイスを作成しました。各クラスはコンストラクターで DbContext を受け入れます。DBAccess プロジェクトから DBContext を渡すだけです。
- MainUI - これは、MVVM レイヤーを格納し、DataBinding などを提供するために DBControl プロジェクトの各クラスを参照します。
EF で単体テストできるように複雑なソリューションを作成するのに時間を費やす代わりに、テスト データが入力されたしっかりしたモック データベースを作成し、単純にコードをモック データベースに向ける方が簡単だという提案を見てきました。生きる。ただし、SQL Server にアクセスする必要がまったくないインメモリ ソリューションを作成できるようにしたいと考えています。
私がこれについてすべて間違っているかどうかを教えてくれるなど、どんな助けも素晴らしいでしょう!!
アップデート:
以下の Paul Kirby によって提供されたソリューションを使用して、「一種の」リポジトリ パターンを作成しました。
インターフェイスを作成しました。
Public Interface IFriendlyRepository(Of T)
ReadOnly Property FriendlyRecords As ObservableCollection(Of T)
Function GetFilteredFriendlyRecords(predicates As List(of Func(Of T, Boolean))) As ObservableCollection(Of T)
Function AddEditFriendlyRecord(ByVal RecordToSave As T) As EntityException
Sub SaveData()
End Interface
次に、このインターフェイスをクラスごとに実装しました。
Namespace Repositories
Public Class clsCurrenciesRepository
Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies)
Private _DBContext As CriticalPathEntities 'The Data Context
Public Sub New(ByVal Context As DbContext)
_DBContext = Context
End Sub
Public ReadOnly Property FriendlyRecords As ObservableCollection(Of FriendlyCurrencies) Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).FriendlyRecords
Get
' We need to convert the results of a Linq to SQL stored procedure to a list,
' otherwise we get an error stating that the query cannot be enumerated twice!
Dim Query = (From Currencies In _DBContext.Currencies.ToList
Group Join CreationUsers In _DBContext.Users.ToList
On Currencies.CreationUserCode Equals CreationUsers.User_Code Into JoinedCreationUsers = Group
From CreationUsers In JoinedCreationUsers.DefaultIfEmpty
Group Join UpdateUsers In _DBContext.Users.ToList
On Currencies.LastUpdateUserCode Equals UpdateUsers.User_Code Into JoinedUpdateUsers = Group
From UpdateUsers In JoinedUpdateUsers.DefaultIfEmpty
Where (Currencies.Deleted = False Or Currencies.Deleted Is Nothing)
Order By Currencies.NAME
Select New FriendlyCurrencies With {.Currency_Code = Currencies.Currency_Code,
.NAME = Currencies.NAME,
.Rate = Currencies.Rate,
.CreatedBy = If(Currencies.CreationUserCode Is Nothing, "", CreationUsers.First_Name & " " & CreationUsers.Last_Name),
.CreationDate = Currencies.CreationDate,
.CreationUserCode = Currencies.CreationUserCode,
.Deleted = Currencies.Deleted,
.LastUpdateDate = Currencies.LastUpdateDate,
.LastUpdatedBy = If(Currencies.LastUpdateUserCode Is Nothing, "", UpdateUsers.First_Name & " " & UpdateUsers.Last_Name),
.LastUpdateUserCode = Currencies.LastUpdateUserCode}).ToList
Return New ObservableCollection(Of FriendlyCurrencies)(Query)
End Get
End Property
Public Function GetFilteredFriendlyRecords(predicates As List(of Func(Of FriendlyCurrencies, Boolean))) As ObservableCollection(Of FriendlyCurrencies) Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).GetFilteredFriendlyRecords
Dim ReturnQuery = FriendlyRecords.ToList
For Each Predicate As Func(Of FriendlyCurrencies, Boolean) In predicates
If Predicate IsNot Nothing Then
ReturnQuery = ReturnQuery.Where(Predicate).ToList
End If
Next
Return New ObservableCollection(Of FriendlyCurrencies)(ReturnQuery)
End Function
Public Function AddEditFriendlyRecord(ByVal RecordToSave As FriendlyCurrencies) As EntityException Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).AddEditFriendlyRecord
Dim dbCurrency As New Currency
' Check if this Staff Member Exists
Dim query = From c In _DBContext.Currencies
Where c.Currency_Code = RecordToSave.Currency_Code
Select c
' If Asset exists, then edit.
If query.Count > 0 Then
dbCurrency = query.FirstOrDefault
Else
'Do Nothing
End If
dbCurrency.Currency_Code = RecordToSave.Currency_Code
dbCurrency.NAME = RecordToSave.NAME
dbCurrency.CreationDate = RecordToSave.CreationDate
dbCurrency.CreationUserCode = RecordToSave.CreationUserCode
dbCurrency.LastUpdateDate = RecordToSave.LastUpdateDate
dbCurrency.LastUpdateUserCode = RecordToSave.LastUpdateUserCode
dbCurrency.Deleted = RecordToSave.Deleted
' Save Asset Object to Database
If query.Count > 0 Then
' If Asset exists, then edit.
Try
'_dbContext.SaveChanges 'We could save here but it's generally bad practice
Catch ex As EntityException
Return ex
End Try
Else
Try
_DBContext.Currencies.Add(dbCurrency)
'_dbContext.SaveChanges 'We could save here but it's generally bad practice
Catch ex As EntityException
Return ex
End Try
End If
Return Nothing
End Function
Public Sub SaveData() Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).SaveData
_DBContext.SaveChanges()
End Sub
End Class
End Namespace
コンストラクター インジェクションを使用して、dbContext をクラスに挿入しました。
既存のコンテキストと"Effort" Unit Testing Toolを使用して、偽の dbContext をモックアップできることを望んでいました。
しかし、私はこれを機能させることができないようです。
暫定的に、ユニット テスト プロジェクトで、ライブ データベースと同じスキーマを使用して、SQLCMD コマンドを使用して (既に存在する場合は) 削除し、空のテスト データベースを作成します。
次に、テスト データベースを参照する dbContext を作成し、テスト データを入力して、これに対してテストします。
注意として、「フレンドリーな」複雑なバージョンではなく、実際の基本エンティティで動作するように「追加/編集」メソッドをリファクタリングします。これは当時最も単純な方法でした。