首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Entity Framework 5实体的深度复制/克隆

Entity Framework 5实体的深度复制/克隆
EN

Stack Overflow用户
提问于 2013-03-09 16:25:41
回答 3查看 44.8K关注 0票数 77

我正在使用Entity Framework5 (DBContext),我正在尝试找到深度复制实体的最佳方法(即复制实体和所有相关对象),然后将新实体保存在数据库中。我该怎么做呢?我曾研究过使用CloneHelper等扩展方法,但我不确定它是否适用于DBContext

EN

回答 3

Stack Overflow用户

发布于 2014-02-12 21:41:41

这里有另一个选择。

在某些情况下,我更喜欢它,因为它不需要您专门运行查询来获得要克隆的数据。您可以使用此方法创建已从数据库中获得的实体的克隆。

代码语言:javascript
复制
//Get entity to be cloned
var source = Context.ExampleRows.FirstOrDefault();

//Create and add clone object to context before setting its values
var clone = new ExampleRow();
Context.ExampleRows.Add(clone);

//Copy values from source to clone
var sourceValues = Context.Entry(source).CurrentValues;
Context.Entry(clone).CurrentValues.SetValues(sourceValues);

//Change values of the copied entity
clone.ExampleProperty = "New Value";

//Insert clone with changes into database
Context.SaveChanges();

此方法将当前值从源复制到已添加的新行。

票数 23
EN

Stack Overflow用户

发布于 2015-10-27 15:01:36

这是一个允许泛型克隆的泛型扩展方法。

您必须从nuget获取System.Linq.Dynamic

代码语言:javascript
复制
    public TEntity Clone<TEntity>(this DbContext context, TEntity entity) where TEntity : class
    {

        var keyName = GetKeyName<TEntity>();
        var keyValue = context.Entry(entity).Property(keyName).CurrentValue;
        var keyType = typeof(TEntity).GetProperty(keyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).PropertyType;

        var dbSet = context.Set<TEntity>();
        var newEntity =  dbSet
            .Where(keyName + " = @0", keyValue)
            .AsNoTracking()
            .Single();

        context.Entry(newEntity).Property(keyName).CurrentValue = keyType.GetDefault();

        context.Add(newEntity);

        return newEntity;
    }

您唯一需要自己实现的就是GetKeyName方法。这可以是从return typeof(TEntity).Name + "Id"return the first guid property的任何内容,也可以返回标记为DatabaseGenerated(DatabaseGeneratedOption.Identity)]的第一个属性。

在我的例子中,我已经用[DataServiceKeyAttribute("EntityId")]标记了类

代码语言:javascript
复制
    private string GetKeyName<TEntity>() where TEntity : class
    {
        return ((DataServiceKeyAttribute)typeof(TEntity)
           .GetCustomAttributes(typeof(DataServiceKeyAttribute), true).First())
           .KeyNames.Single();
    }
票数 2
EN

Stack Overflow用户

发布于 2019-02-04 16:23:29

我在Entity Framework Core中遇到了同样的问题,当子实体被延迟加载时,深度克隆涉及多个步骤。克隆整个结构的一种方法如下:

代码语言:javascript
复制
   var clonedItem = Context.Parent.AsNoTracking()
        .Include(u => u.Child1)
        .Include(u => u.Child2)
        // deep includes might go here (see ThenInclude)
        .FirstOrDefault(u => u.ParentId == parentId);

    // remove old id from parent
    clonedItem.ParentId = 0;

    // remove old ids from children
    clonedItem.Parent1.ForEach(x =>
    {
        x.Child1Id = 0;
        x.ParentId= 0;
    });
    clonedItem.Parent2.ForEach(x =>
    {
        x.Child2Id = 0;
        x.ParentId= 0;
    });

    // customize entities before inserting it

    // mark everything for insert
    Context.Parent.Add(clonedItem);

    // save everything in one single transaction
    Context.SaveChanges();

当然,有一些方法可以让泛型函数急于加载所有内容和/或重置所有键的值,但这应该使所有步骤变得非常清晰和可定制(例如,对于某些子项,通过跳过它们的包含,所有步骤都不被克隆)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15308747

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档