开发者

How to do a simple entity copy in Linq-to-SQL?

When using a Linq-to-SQL class, how can I make a simple copy of an entity and save it?

My entity has a guid for a unique ID that gets automatically generated in the SQL Server.

I don't require a "deep clone".

I tried to use some clone methods that are out there but I couldn't figure out how to get everything serialized that needed to be serialized (got stuck on the DataContext not being serializable).

Can I just get an entity, detach it from the DataContext, null out the unique ID and InsertOnSubmit in a new DataContext? If so, how would I do this?

VB.net code preferred but not required.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

UPDATE:

Public Shared Function ReIssue(RequestID As Guid) As Guid

    Dim req As Request
    Dim new_req As Request

    Using dc1 As New MBDataContext()
        req = (From r In dc1.Requests Where r.ID = RequestID).Single()
    End Using

    new_req = req
    new_req.ID = Guid.Empty
    new_req.CreateDate = Nothing

    Using dc2 As New MBDataContext()
        dc2.Requests.InsertOnSubmit(new_req)
        dc2.SubmitChanges()
   开发者_StackOverflow End Using

End Function

I get an error: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.

on this line: dc2.Requests.InsertOnSubmit(new_req)


Nulling out the unique id and then calling InsertOnSubmit is the right way to go. Some things you have to consider though:

  • What is the type of the id? Is it an int? A Guid? Is it nullable? If it is nullable, make sure to set it to null, if it is an int, then to 0, or a Guid, then to Guid.Empty.
  • Does the type have a timestamp of some kind? If so, then you have to reset/set it to null as well, depending on the type.

Once you've done that, you can call InsertOnSubmit and then SubmitChanges and the change should take place.

Note, if you are doing this for a large number of records, you are better off writing a stored procedure which will perform the insert into the table using a select from the other table. It will be much faster that way (you won't be loading the data from the database into memory then pushing it back, inserting the records one at a time).


This method seems to have worked perfectly.

Making the final code look like this:

Public Shared Function ReIssue(RequestID As Guid) As Guid

    Using dc As New MBDataContext()
        Dim req As Request
        req = (From r In dc.Requests Where r.ID = RequestID).Single()

        Dim new_req As Request = DirectCast(Entity.Copy(req, New Request()), Request)

        dc.Requests.InsertOnSubmit(new_req)
        dc.SubmitChanges()

        req.ActiveRequestParentID = new_req.ID
        dc.SubmitChanges()

        Return new_req.ID
    End Using

End Function

Public NotInheritable Class Entity

    Private Sub New()
    End Sub

    Public Shared Function Copy(source As Object, destination As Object) As Object
        Dim sourceProps As System.Reflection.PropertyInfo() = source.[GetType]().GetProperties()
        Dim destinationProps As System.Reflection.PropertyInfo() = destination.[GetType]().GetProperties()
        For Each sourceProp As System.Reflection.PropertyInfo In sourceProps
            Dim column As ColumnAttribute = TryCast(Attribute.GetCustomAttribute(sourceProp, GetType(ColumnAttribute)), ColumnAttribute)
            If column IsNot Nothing AndAlso Not column.IsPrimaryKey Then
                For Each destinationProp As System.Reflection.PropertyInfo In destinationProps
                    If sourceProp.Name = destinationProp.Name AndAlso destinationProp.CanWrite Then
                        destinationProp.SetValue(destination, sourceProp.GetValue(source, Nothing), Nothing)
                        Exit For
                    End If
                Next
            End If
        Next
        Return destination
    End Function

End Class
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜