实体框架:为什么这段代码不起作用 [英] Entity Framework : Why this code doesn't work
问题描述
导入System.Data.Objects
导入System.Data.Objects.DataClasses
导入System.Runtime.CompilerServices
公共模块实体
< Extension()>
公共函数CloneEntity(Of As As Class)(entity As T,context As ObjectContext,Optional include As List(Of IncludeEntity)= Nothing,Optional copyKeys As Boolean = False)As T
返回CloneEntityHelper (上下文,包括,copyKeys)
结束函数
私有函数CloneEntityHelper(Of As As Class)(entity As T,context As ObjectContext,Optional include As List(Of IncludeEntity)= Nothing,可选的copyKeys As Boolean = False)As T
如果include Is Nothing然后include =新列表(包含实例)()
Dim myType = entity.GetType()
Dim methodInfo = context.GetType ().GetMethod(CreateObject)。MakeGenericMethod(myType)
Dim result = methodInfo.Invoke(context,Nothing)
Dim propertyInfo = entity.GetType()。GetProperties()
每个信息在propertyInfo
Dim attributes = info.GetCustomAttributes(GetType(EdmScalarPropertyAttribute),False).ToList()
对于每个attr作为EdmScalarPropertyAttribute在属性
如果(不是copyKeys)AndAlso attr.EntityKeyProperty
继续为
结束如果
info.SetValue(result,info.GetValue(entity,Nothing),Nothing)
Next
如果info.PropertyType.Name.Equals(EntityCollection \"1,StringComparison.OrdinalIgnoreCase)然后
Dim shouldInclude = include.SingleOrDefault(Function(i)i.Name.Equals(info.Name, StringComparison.OrdinalIgnoreCase))
如果shouldInclude是Nothing然后继续为
Dim relatedChildren = info.GetValue(entity,Nothing)
Dim propertyType As Type = relatedChildren.GetType()。GetGenericArguments()。 First()
Dim genericType As Type = GetType(EntityCollection(Of))
Dim boundType = genericType.MakeGenericType(propertyType)
Dim children = Activator.CreateInstance(boundType)
For每个孩子在relatedChildren
Dim cloneChild = CloneEntityHelper(child,context,shouldInclude.Children, shouldInclude.CopyKeys)
children.Add(cloneChild)
下一个
info.SetValue(result,children,Nothing)
End If
Next
返回结果
结束函数
公共类IncludeEntity
公共属性名称作为字符串
公共属性儿童作为新列表(IncludeEntity)
公共属性CopyKeys As Boolean
Public Sub New(propertyName As String,ParamArray childNodes()As String)
Name = propertyName
Children = childNodes.Select(Function(n )new IncludeEntity(n))ToList()
End Sub
结束类
结束模块
现在我正在使用如下代码:
Dim litm,newitm As New MyObject
Dim inc =新列表(IncludeEntity)()
inc.Add(New IncludeEntity(Child_list))
litm = context.MyObjects.FirstOrDefault
newitm = litm.CloneEntity (CType(context,Entity.Infrastructure.IObjectCont extAdapter).ObjectContext,include:= inc)
代码执行没有错误,但没有复制,所以 newitm
是空的。
我已经检查了代码,发现这行在$ c> CloneEntity function:
Dim myType = entity.GetType()
产生一种奇怪的类型。
我期待着类型将为 MyObject
类型,而是返回:
MyObject_F2FFE64DA472EB2B2BDF7E143DE887D3845AD9D1731FD3107937062AC0C2E4BB
这一行也是:
Dim result = methodInfo.Invoke(context,Nothing)
产生相同奇怪的类型。
我不知道这是否是问题,但这是我注意到的唯一奇怪的事情。
你能帮我找出为什么这段代码不行吗?
谢谢!
实体框架与许多其他ORM一样将为您的实体构建代理类型它可以拦截到:
- 当您访问这些集合属性时,懒惰加载包含在您的实体中的属性的任何集合的内容。
- 检测您作为脏检查的一部分对实例的属性进行了更改,以便在调用 时,将知道哪些对象是脏的并且需要保存到数据库中code> SaveChanges 。
参考例如EF返回代理类而不是实际实体或使用代理。
如果你想找出您的实体的底层类型由t包装他代理,即与您正在寻找的类型匹配的代理(例如, MyObject
),您可以使用对象上下文中的方法:
var underlyingType = ObjectContext.GetObjectType(entity.GetType());
I'm using Entity Framework 6.0, DbContext. I'm using this method to copy an object and some related children:
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Imports System.Runtime.CompilerServices
Public Module Entities
<Extension()>
Public Function CloneEntity(Of T As Class)(entity As T, context As ObjectContext, Optional include As List(Of IncludeEntity) = Nothing, Optional copyKeys As Boolean = False) As T
Return CloneEntityHelper(entity, context, include, copyKeys)
End Function
Private Function CloneEntityHelper(Of T As Class)(entity As T, context As ObjectContext, Optional include As List(Of IncludeEntity) = Nothing, Optional copyKeys As Boolean = False) As T
If include Is Nothing Then include = New List(Of IncludeEntity)()
Dim myType = entity.GetType()
Dim methodInfo = context.GetType().GetMethod("CreateObject").MakeGenericMethod(myType)
Dim result = methodInfo.Invoke(context, Nothing)
Dim propertyInfo = entity.GetType().GetProperties()
For Each info In propertyInfo
Dim attributes = info.GetCustomAttributes(GetType(EdmScalarPropertyAttribute), False).ToList()
For Each attr As EdmScalarPropertyAttribute In attributes
If (Not copyKeys) AndAlso attr.EntityKeyProperty
Continue For
End If
info.SetValue(result, info.GetValue(entity, Nothing), Nothing)
Next
If info.PropertyType.Name.Equals("EntityCollection`1", StringComparison.OrdinalIgnoreCase) Then
Dim shouldInclude = include.SingleOrDefault(Function(i) i.Name.Equals(info.Name, StringComparison.OrdinalIgnoreCase))
If shouldInclude Is Nothing Then Continue For
Dim relatedChildren = info.GetValue(entity, Nothing)
Dim propertyType As Type = relatedChildren.GetType().GetGenericArguments().First()
Dim genericType As Type = GetType(EntityCollection(Of ))
Dim boundType = genericType.MakeGenericType(propertyType)
Dim children = Activator.CreateInstance(boundType)
For Each child In relatedChildren
Dim cloneChild = CloneEntityHelper(child, context, shouldInclude.Children, shouldInclude.CopyKeys)
children.Add(cloneChild)
Next
info.SetValue(result, children, Nothing)
End If
Next
Return result
End Function
Public Class IncludeEntity
Public Property Name As String
Public Property Children As New List(Of IncludeEntity)
Public Property CopyKeys As Boolean
Public Sub New(propertyName As String, ParamArray childNodes() As String)
Name = propertyName
Children = childNodes.Select(Function(n) new IncludeEntity(n)).ToList()
End Sub
End Class
End Module
Now I'm using the code like below :
Dim litm, newitm As New MyObject
Dim inc = New List(Of IncludeEntity)()
inc.Add(New IncludeEntity("Child_list"))
litm=context.MyObjects.FirstOrDefault
newitm = litm.CloneEntity(CType(context, Entity.Infrastructure.IObjectContextAdapter).ObjectContext,include:=inc)
The code is executed without errors, but nothing is copied, so newitm
is empty.
I have inspected the code and found that this line on the CloneEntity
function :
Dim myType = entity.GetType()
Is producing a strange type.
I'm expecting that the type will be of MyObject
type, but instead this return :
MyObject_F2FFE64DA472EB2B2BDF7E143DE887D3845AD9D1731FD3107937062AC0C2E4BB
This line too :
Dim result = methodInfo.Invoke(context, Nothing)
produces the same strange type.
I don't know if this is the problem, but this is the only strange thing I have noticed.
Can you help me to find out why this code doesn't work?
Thank you!
Entity framework, like many other ORMs will build a proxy type for your entities so that it can intercept calls to:
- Lazy load the contents of any collection contained as properties within your entity, when you access those collection properties.
- Detect that you have made changes to the properties of an instance as part of dirty checking, so that it will know which objects are dirty and need to be saved to the database when you invoke
SaveChanges
.
Refer for example to EF returning proxy class instead of actual entity or Working with Proxies.
If you want to find out the underlying type of your entity that is wrapped by the proxy, i.e. the one that would match with the type you are looking for (e.g. MyObject
), you can do that using a method in the object context:
var underlyingType = ObjectContext.GetObjectType(entity.GetType());
这篇关于实体框架:为什么这段代码不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!