我想我会为此添加我的贡献。它是一个 VB 实现,是对代码项目中现有代码的补充。
此实现允许包含关系属性(但您必须指定这一点)。
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Imports System.Runtime.CompilerServices
Public Module Entities
''' <summary>
''' Clone an entity
''' </summary>
''' <remarks>
''' Inspiration from: http://www.codeproject.com/Tips/474296/Clone-an-Entity-in-Entity-Framework-4
''' </remarks>
<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
' Set default parameter values
If include Is Nothing Then include = New List(Of IncludeEntity)()
'If visited Is Nothing Then visited = New List(Of String)()
' Get the type of entity we are dealing with
Dim myType = entity.GetType()
' Make a copy of this object
Dim methodInfo = context.GetType().GetMethod("CreateObject").MakeGenericMethod(myType)
Dim result = methodInfo.Invoke(context, Nothing)
' Get the property information for the source object
Dim propertyInfo = entity.GetType().GetProperties()
' Copy over the property information
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
' Handle relational properties
If info.PropertyType.Name.Equals("EntityCollection`1", StringComparison.OrdinalIgnoreCase) Then
' Determine whether or not we are allowed to deal with this relationship
Dim shouldInclude = include.SingleOrDefault(Function(i) i.Name.Equals(info.Name, StringComparison.OrdinalIgnoreCase))
If shouldInclude Is Nothing Then Continue For
' Clone the property
Dim relatedChildren = info.GetValue(entity, Nothing)
' Get an EntityCollection instance to hold the relational entries
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)
' Load the children into the property
For Each child In relatedChildren
Dim cloneChild = CloneEntityHelper(child, context, shouldInclude.Children, shouldInclude.CopyKeys)
children.Add(cloneChild)
Next
' Save this value
info.SetValue(result, children, Nothing)
End If
Next
Return result
End Function
''' <summary>
''' Represent which (relational) properties should be included
''' </summary>
Public Class IncludeEntity
''' <summary>
''' Name of the relationship to include
''' </summary>
Public Property Name As String
''' <summary>
''' Relationships to include from the selected property
''' </summary>
Public Property Children As New List(Of IncludeEntity)
''' <summary>
''' Whether or not to Copy keys
''' </summary>
Public Property CopyKeys As Boolean
''' <summary>
''' Empty Constructor
''' </summary>
Public Sub New()
End Sub
''' <summary>
''' Create with single children
''' </summary>
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
以及一个示例用法:
Dim formToClone = con.SF_Forms.FirstOrDefault(Function(e) e.Form_id = f.Id)
' Define what should be copied
Dim inc = New List(Of IncludeEntity)()
Dim validation = New IncludeEntity("SF_Questions_validation", "SF_Validation_Parameters")
Dim questions = new IncludeEntity("SF_Questions", "SF_Question_Parameters")
questions.Children.Add(validation)
Dim questionGroups = new IncludeEntity("SF_Question_Groups")
questionGroups.Children.Add(questions)
Dim actions = New IncludeEntity("SF_Actions", "SF_Action_Parameters")
inc.Add(questionGroups)
inc.Add(actions)
inc.Add(new IncludeEntity("SF_Messages"))
' Save the cloned form
Dim clonedForm = formToClone.CloneEntity(con, include := inc)
我花了一段时间才弄清楚如何处理关系方面,所以希望这会对某人有所帮助。