如何创建和填充 DbSet(Of T)?
How to create and populate a DbSet(Of T)?
我正在模拟 DbContext
,我需要 .Set(Of TEntity)
方法来 return 底层数据存储的内容(在本例中是 List(Of TEntity)
)。
这是我的 .Setup()
扩展方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of Db.Context), Entities As List(Of TEntity))
Dim oReturn As Func(Of DbSet(Of TEntity))
Dim oSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
oReturn = Function() Entities.AsQueryable
oSetup = Function(Context) Context.Set(Of TEntity)
Instance.Setup(oSetup).Returns(oReturn)
End Sub
问题是oReturn
函数运行时,出现错误:
Unable to cast object of type IQueryable'1[Item]
to type DbSet'1[Item]
由于DbSet(Of TEntity)
是抽象的class,不能直接实例化。似乎没有办法将该数据放入 DbSet
。 (旁注:这加深了 EF 本身如何管理任务的神秘感——我浏览了一下源代码,但一无所获。)
.AsEnumerable
和 .ToArray
都不起作用。相同的转换错误。
有 this answer,但我无法进行类似的调整,因为这个 DbContext
也用于管理我的 ASP.NET 身份存储——存储库模式不适用在我的代码中普遍存在。我必须改为模拟 DbContext
。
然后是 this question,但仍未得到答复。
如何将 List(Of TEntity)
数据放入 DbSet(Of TEntity)
?
我不是通过创建和填充一个新的 DbSet(Of TEntity)
来做到这一点的,正如这个问答标题所假设的那样,而是通过模拟 DbSet(Of TEntity)
:
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of Db.Context), Entities As List(Of TEntity), ContextSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity))))
Dim oDbSetReturn As Func(Of DbSet(Of TEntity))
Dim oDbSetSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
Dim oDbSetMock As Mock(Of DbSet(Of TEntity))
Dim oDbSet As DbSet(Of TEntity)
oDbSetMock = New Mock(Of DbSet(Of TEntity))
oDbSetMock.Setup(Entities)
oDbSet = oDbSetMock.Object
oDbSetReturn = Function() oDbSet
oDbSetSetup = Function(Context) Context.Set(Of TEntity)
Instance.Setup(ContextSetup).Returns(oDbSet)
Instance.Setup(oDbSetSetup).Returns(oDbSetReturn)
End Sub
这是 DbSet(Of TEntity)
设置的配套方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of DbSet(Of TEntity)), Entities As List(Of TEntity))
Dim oRemoveRangeReturn As Func(Of IEnumerable(Of TEntity), IEnumerable(Of TEntity))
Dim oRemoveRangeSetup As Expression(Of Func(Of DbSet(Of TEntity), IEnumerable(Of TEntity)))
Dim oAddRangeReturn As Func(Of IEnumerable(Of TEntity), IEnumerable(Of TEntity))
Dim oAddRangeSetup As Expression(Of Func(Of DbSet(Of TEntity), IEnumerable(Of TEntity)))
Dim oRemoveReturn As Func(Of TEntity, TEntity)
Dim oRemoveSetup As Expression(Of Func(Of DbSet(Of TEntity), TEntity))
Dim oAddReturn As Func(Of TEntity, TEntity)
Dim oAddSetup As Expression(Of Func(Of DbSet(Of TEntity), TEntity))
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.GetEnumerator).Returns(Entities.AsQueryable.GetEnumerator)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.ElementType).Returns(Entities.AsQueryable.ElementType)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.Expression).Returns(Entities.AsQueryable.Expression)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.Provider).Returns(Entities.AsQueryable.Provider)
oRemoveRangeSetup = Function(DbSet) DbSet.RemoveRange(It.IsAny(Of IEnumerable(Of TEntity)))
oAddRangeSetup = Function(DbSet) DbSet.AddRange(It.IsAny(Of IEnumerable(Of TEntity)))
oRemoveSetup = Function(DbSet) DbSet.Remove(It.IsAny(Of TEntity))
oAddSetup = Function(DbSet) DbSet.Add(It.IsAny(Of TEntity))
oRemoveRangeReturn = Function(Range)
Entities = Entities.Except(Range)
Return Entities
End Function
oAddRangeReturn = Function(Range)
Entities.AddRange(Range)
Return Entities
End Function
oRemoveReturn = Function(Entity)
Entities.Remove(Entity)
Return Entity
End Function
oAddReturn = Function(Entity)
Entities.Add(Entity)
Return Entity
End Function
Instance.Setup(oRemoveRangeSetup).Returns(oRemoveRangeReturn)
Instance.Setup(oAddRangeSetup).Returns(oAddRangeReturn)
Instance.Setup(oRemoveSetup).Returns(oRemoveReturn)
Instance.Setup(oAddSetup).Returns(oAddReturn)
End Sub
它的名字是这样的:
Private ReadOnly Property DbContextFactory As Func(Of Db.Context)
Get
Dim oContextMock As Mock(Of Db.Context)
Return Function()
oContextMock = New Mock(Of Db.Context)
oContextMock.Setup(Of Db.City)(Me.Cities, Function(Context) Context.Cities)
oContextMock.Setup(Of Db.Role)(Me.Roles, Function(Context) Context.Roles)
oContextMock.Setup(Of Db.User)(Me.Users, Function(Context) Context.Users)
Return oContextMock.Object
End Function
End Get
End Property
这应该有效。我目前无法对其进行测试,但我会尽快进行测试并提供结果。
--编辑 1--
我在 Instance.Setup(ContextSetup)
收到 'Unsupported Expression' 错误。为此,我已经 opened a ticket 在最小起订量仓库中。
--编辑 2--
再一次,stakx
来救援。
答案在铸件中。大多数模型想要 DbSet(Of T)
,而两个 Identity-derived 模型(Db.Role
和 Db.User
)想要 IDbSet(Of T)
.
这导致一对重载的扩展方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(
Instance As Mock(Of Db.Context),
Entities As List(Of TEntity),
DbSetSetup As Expression(Of Func(Of Db.Context, IDbSet(Of TEntity)))
)
Instance.Setup(DbSetSetup).Returns(DbSet(Entities))
Instance.Setup(MethodSetup(Of TEntity)).Returns(MethodReturn(Entities))
End Sub
<Extension>
Public Sub Setup(Of TEntity As Class)(
Instance As Mock(Of Db.Context),
Entities As List(Of TEntity),
DbSetSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
)
Instance.Setup(DbSetSetup).Returns(DbSet(Entities))
Instance.Setup(MethodSetup(Of TEntity)).Returns(MethodReturn(Entities))
End Sub
Private Function MethodSetup(Of TEntity As Class)() As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
Return Function(Context) Context.Set(Of TEntity)
End Function
Private Function MethodReturn(Of TEntity As Class)(Entities As List(Of TEntity)) As Func(Of DbSet(Of TEntity))
Return Function() DbSet(Entities)
End Function
Private Function DbSet(Of TEntity As Class)(Entities As List(Of TEntity)) As DbSet(Of TEntity)
With New Mock(Of DbSet(Of TEntity))
.Setup(Entities)
Return .Object
End With
End Function
最后一切正常。
谢谢stakx
。
我正在模拟 DbContext
,我需要 .Set(Of TEntity)
方法来 return 底层数据存储的内容(在本例中是 List(Of TEntity)
)。
这是我的 .Setup()
扩展方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of Db.Context), Entities As List(Of TEntity))
Dim oReturn As Func(Of DbSet(Of TEntity))
Dim oSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
oReturn = Function() Entities.AsQueryable
oSetup = Function(Context) Context.Set(Of TEntity)
Instance.Setup(oSetup).Returns(oReturn)
End Sub
问题是oReturn
函数运行时,出现错误:
Unable to cast object of type
IQueryable'1[Item]
to typeDbSet'1[Item]
由于DbSet(Of TEntity)
是抽象的class,不能直接实例化。似乎没有办法将该数据放入 DbSet
。 (旁注:这加深了 EF 本身如何管理任务的神秘感——我浏览了一下源代码,但一无所获。)
.AsEnumerable
和 .ToArray
都不起作用。相同的转换错误。
有 this answer,但我无法进行类似的调整,因为这个 DbContext
也用于管理我的 ASP.NET 身份存储——存储库模式不适用在我的代码中普遍存在。我必须改为模拟 DbContext
。
然后是 this question,但仍未得到答复。
如何将 List(Of TEntity)
数据放入 DbSet(Of TEntity)
?
我不是通过创建和填充一个新的 DbSet(Of TEntity)
来做到这一点的,正如这个问答标题所假设的那样,而是通过模拟 DbSet(Of TEntity)
:
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of Db.Context), Entities As List(Of TEntity), ContextSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity))))
Dim oDbSetReturn As Func(Of DbSet(Of TEntity))
Dim oDbSetSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
Dim oDbSetMock As Mock(Of DbSet(Of TEntity))
Dim oDbSet As DbSet(Of TEntity)
oDbSetMock = New Mock(Of DbSet(Of TEntity))
oDbSetMock.Setup(Entities)
oDbSet = oDbSetMock.Object
oDbSetReturn = Function() oDbSet
oDbSetSetup = Function(Context) Context.Set(Of TEntity)
Instance.Setup(ContextSetup).Returns(oDbSet)
Instance.Setup(oDbSetSetup).Returns(oDbSetReturn)
End Sub
这是 DbSet(Of TEntity)
设置的配套方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of DbSet(Of TEntity)), Entities As List(Of TEntity))
Dim oRemoveRangeReturn As Func(Of IEnumerable(Of TEntity), IEnumerable(Of TEntity))
Dim oRemoveRangeSetup As Expression(Of Func(Of DbSet(Of TEntity), IEnumerable(Of TEntity)))
Dim oAddRangeReturn As Func(Of IEnumerable(Of TEntity), IEnumerable(Of TEntity))
Dim oAddRangeSetup As Expression(Of Func(Of DbSet(Of TEntity), IEnumerable(Of TEntity)))
Dim oRemoveReturn As Func(Of TEntity, TEntity)
Dim oRemoveSetup As Expression(Of Func(Of DbSet(Of TEntity), TEntity))
Dim oAddReturn As Func(Of TEntity, TEntity)
Dim oAddSetup As Expression(Of Func(Of DbSet(Of TEntity), TEntity))
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.GetEnumerator).Returns(Entities.AsQueryable.GetEnumerator)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.ElementType).Returns(Entities.AsQueryable.ElementType)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.Expression).Returns(Entities.AsQueryable.Expression)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.Provider).Returns(Entities.AsQueryable.Provider)
oRemoveRangeSetup = Function(DbSet) DbSet.RemoveRange(It.IsAny(Of IEnumerable(Of TEntity)))
oAddRangeSetup = Function(DbSet) DbSet.AddRange(It.IsAny(Of IEnumerable(Of TEntity)))
oRemoveSetup = Function(DbSet) DbSet.Remove(It.IsAny(Of TEntity))
oAddSetup = Function(DbSet) DbSet.Add(It.IsAny(Of TEntity))
oRemoveRangeReturn = Function(Range)
Entities = Entities.Except(Range)
Return Entities
End Function
oAddRangeReturn = Function(Range)
Entities.AddRange(Range)
Return Entities
End Function
oRemoveReturn = Function(Entity)
Entities.Remove(Entity)
Return Entity
End Function
oAddReturn = Function(Entity)
Entities.Add(Entity)
Return Entity
End Function
Instance.Setup(oRemoveRangeSetup).Returns(oRemoveRangeReturn)
Instance.Setup(oAddRangeSetup).Returns(oAddRangeReturn)
Instance.Setup(oRemoveSetup).Returns(oRemoveReturn)
Instance.Setup(oAddSetup).Returns(oAddReturn)
End Sub
它的名字是这样的:
Private ReadOnly Property DbContextFactory As Func(Of Db.Context)
Get
Dim oContextMock As Mock(Of Db.Context)
Return Function()
oContextMock = New Mock(Of Db.Context)
oContextMock.Setup(Of Db.City)(Me.Cities, Function(Context) Context.Cities)
oContextMock.Setup(Of Db.Role)(Me.Roles, Function(Context) Context.Roles)
oContextMock.Setup(Of Db.User)(Me.Users, Function(Context) Context.Users)
Return oContextMock.Object
End Function
End Get
End Property
这应该有效。我目前无法对其进行测试,但我会尽快进行测试并提供结果。
--编辑 1--
我在 Instance.Setup(ContextSetup)
收到 'Unsupported Expression' 错误。为此,我已经 opened a ticket 在最小起订量仓库中。
--编辑 2--
再一次,stakx
来救援。
答案在铸件中。大多数模型想要 DbSet(Of T)
,而两个 Identity-derived 模型(Db.Role
和 Db.User
)想要 IDbSet(Of T)
.
这导致一对重载的扩展方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(
Instance As Mock(Of Db.Context),
Entities As List(Of TEntity),
DbSetSetup As Expression(Of Func(Of Db.Context, IDbSet(Of TEntity)))
)
Instance.Setup(DbSetSetup).Returns(DbSet(Entities))
Instance.Setup(MethodSetup(Of TEntity)).Returns(MethodReturn(Entities))
End Sub
<Extension>
Public Sub Setup(Of TEntity As Class)(
Instance As Mock(Of Db.Context),
Entities As List(Of TEntity),
DbSetSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
)
Instance.Setup(DbSetSetup).Returns(DbSet(Entities))
Instance.Setup(MethodSetup(Of TEntity)).Returns(MethodReturn(Entities))
End Sub
Private Function MethodSetup(Of TEntity As Class)() As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
Return Function(Context) Context.Set(Of TEntity)
End Function
Private Function MethodReturn(Of TEntity As Class)(Entities As List(Of TEntity)) As Func(Of DbSet(Of TEntity))
Return Function() DbSet(Entities)
End Function
Private Function DbSet(Of TEntity As Class)(Entities As List(Of TEntity)) As DbSet(Of TEntity)
With New Mock(Of DbSet(Of TEntity))
.Setup(Entities)
Return .Object
End With
End Function
最后一切正常。
谢谢stakx
。