Cloning data on Entity Framework

前端 未结 6 1669
轻奢々
轻奢々 2020-12-02 09:53

I am creating software where user can create new product based on older product.

Now I need to make copying / cloning operations with Entity Framework. First I start

相关标签:
6条回答
  • 2020-12-02 10:15

    Using straight serialization, you can do this:

    http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/a967b44b-c85c-4afd-a499-f6ff604e2139/

    Using Reflection, but with lots more code you can do this: http://msmvps.com/blogs/matthieu/archive/2008/05/31/entity-cloner.aspx

    0 讨论(0)
  • 2020-12-02 10:19

    If you want to create a copy of an entity for comparison later in your code execution, you can select the entity in a new db context.

    If for example you are updating an entity, then later in the code you want to compare the updated and original entity:

    var db = new dbEntityContext();
    var dbOrig = new dbEntityContext();
    
    var myEntity = db.tblData.FirstOrDefault(t => t.Id == 123);
    var myEntityOrig = dbOrig.tblData.FirstOrDefault(t => t.Id == 123);
    
    //Update the entity with changes
    myEntity.FirstName = "Gary";
    
    //Save Changes
    db.SaveChnages();
    

    At this point, myEntity.FirstName will contain "Gary" whilst myEntityOrig.FirstName will contain the original value. Useful if you have a function to log changes where you can pass in the updated and original entity.

    0 讨论(0)
  • 2020-12-02 10:21

    A really short way of duplicating entities using generics (VB, sorry).
    It copies foreign key values (external IDs) but doesn't load their related objects.

    <Extension> _
    Public Function DuplicateEntity(Of T As {New, Class})(ctx As myContext, ent As T) As T
        Dim other As New T 'T is a proxy type, but New T creates a non proxy instance
        ctx.Entry(other).State = EntityState.Added 'attaches it to ctx
        ctx.Entry(other).CurrentValues.SetValues(ent) 'copies primitive properties
        Return other
    End Function
    

    For instance:

    newDad = ctx.DuplicateEntity(oDad)
    newDad.RIDGrandpa ' int value copied
    newDad.Grandpa    ' object for RIDGrandpa above, equals Nothing(null)
    newDad.Children   ' nothing, empty
    

    I don't know exactly how to reload Grandpa in this case.
    This doesn't work:

    ctx.SaveChanges()
    ctx.Entry(newDad).Reload()
    

    but really, no problem. I would rather assign Grandpa by hand if I need it.

    newDad.Grandpa = oDad.Grandpa
    

    EDIT: As MattW proposes in his comment, detaching and finding the new entity you get its children loaded (not collections).

    ctx.Entry(newDad).State = EntityState.Detached
    ctx.Find(newDad.RowId) 'you have to know the key name
    
    0 讨论(0)
  • 2020-12-02 10:22

    To add a new row whose content is based on an existing row, follow these steps:

    1. Get an entity based on the starting row.
    2. Set the entry state for the entity to Added.
    3. Modify the entity.
    4. Save changes.

    Here's an example:

    var rabbit = db.Rabbits.First(r => r.Name == "Hopper");
    db.Entry(rabbit).State = EntityState.Added;
    rabbit.IsFlop = false;
    db.SaveChanges();
    
    0 讨论(0)
  • 2020-12-02 10:31

    To clone an Entity in Entity Framework you could simply Detach the entity from the DataContext and then re-add it to the EntityCollection.

    context.Detach(entity);
    entityCollection.Add(entity);
    

    Update for EF6+ (from comments)

    context.Entry(entity).State = EntityState.Detached;
    entity.id = 0;
    entity.property = value;
    context.Entry(entity).State = EntityState.Added;
    context.SaveChanges();
    
    0 讨论(0)
  • 2020-12-02 10:31
    public static EntityObject Clone(this EntityObject Entity)
    {
        var Type = Entity.GetType();
        var Clone = Activator.CreateInstance(Type);
    
        foreach (var Property in Type.GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.SetProperty))
        {
            if (Property.PropertyType.IsGenericType && Property.PropertyType.GetGenericTypeDefinition() == typeof(EntityReference<>)) continue;
            if (Property.PropertyType.IsGenericType && Property.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>)) continue;
            if (Property.PropertyType.IsSubclassOf(typeof(EntityObject)))  continue;
    
            if (Property.CanWrite)
            {
                Property.SetValue(Clone, Property.GetValue(Entity, null), null);
            }
        }
    
        return (EntityObject)Clone;
    }
    

    This is a simple method I wrote. It should work for most people.

    0 讨论(0)
提交回复
热议问题