PGa*_*her 4 vb.net entity-framework dependency-injection ef-database-first entity-framework-5
我正在寻找使用Entity Framework 5和Database First(连接到SQL Server 2008 R2)创建VB.NET 11 WPF MVVM应用程序.
我选择了Database First,因为我正在将现有解决方案迁移到WPF MVVM,当然数据库已经存在.
我想开始使用依赖注入,所以我可以尽可能多地对我的代码进行单元测试.
我似乎无法找到如何使用依赖注入与EF DB-First,特别是与vb.net一起使用的简明扼要的演练.虽然即使是C#的例子也不错,但我确定.
我真正喜欢的是一个简单的一步一步的指南,解释如何设置解决方案,如何设置每个部分准备好依赖注入等,但这些似乎很难得到.
到目前为止,我已经创建了解决方案及其项目,如下所示;
我已经看到建议,不是花时间编写复杂的解决方案,以便能够使用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
Run Code Online (Sandbox Code Playgroud)
然后我逐个类地实现了这个接口;
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
Run Code Online (Sandbox Code Playgroud)
我使用构造函数注入将dbContext插入到类中.
我原本希望能够使用我现有的上下文和"Effort"单元测试工具来模拟一个假的dbContext .
但是,我似乎无法让这个工作.
在此期间,在我的单元测试项目中,我正在删除(如果它已经存在)并使用SQLCMD命令创建一个空的测试数据库,使用与我的实时数据库相同的模式.
然后,我创建一个引用测试数据库的dbContext,用测试数据填充它,并对此进行测试.
作为一个注释,我将重构我的"添加/编辑"方法来处理实际的基本实体,而不是我的"友好"复杂版本,这是当时最简单的方法.
如果您正在使用DB-first,这就是我的建议.
完成后,您可能希望查看类似工作单元模式的内容.这是一个快速的代码示例,我将在之后解释它.
public interface IUnitOfWork
{
IDbSet<Location> Locations { get; }
void Commit();
}
public class EFUnitOfWork : IUnitOfWork
{
private readonly YourGeneratedDbContext _context;
public EFUnitOfWork(string connectionString)
{
_context = new YourGeneratedDbContext();
}
public IDbSet<Location> Locations
{
get { return _context.Locations; }
}
public void Commit()
{
_context.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个基本的工作单元,它公开了一些Locations列表作为一个例子(抱歉它在C#中,但我不太熟悉VB).
请注意,这是暴露IDbSet对象 - 这就是神奇进来如果您DBACCESS项目,您使用的工作或存储库模式隐藏EF的这个单位,因为它实现了一个接口,并返回IDbSet对象,任何地方,需要您的数据可能有这样的IUnitOfWork构造注入DI,并替换为一个嘲笑的版本,返回模拟IDbSet对象(他们只是在最后IQueryables)当你需要进行单元测试.
您可能会发现,通过新模板中的POCO生成,您甚至可以放弃在DBControl项目中执行的大量工作.
无论如何,这只是定位项目以获得最佳单元测试和DI的基本内容.
| 归档时间: |
|
| 查看次数: |
3285 次 |
| 最近记录: |