在EF核心中克隆对象时如何正确获取父ID的新外键值 创建克隆 IdFactory 用法

给出该模型

   public class Record
   {
     public int Id { get; set; }
     public string Title { get; set; }
     public int? ParentId { get; set; }
   }

克隆前记录

            // here is the Records List Before Cloning ClonedRecords
            //    Id        ParentId
            //    ---       --------
            //     1         null 
            //     2          1 

克隆记录的方法

static List<Record> Clone(List<Record> records)
    {
        var clone = new List<Record>();
        foreach(var item in records)
        {
            clone.Add(new Record {
               Title = item.Title,ParentId = null  // I  want to Map the ParentId to the new created add and not the old value
            });

        }
    }

我的问题是克隆版本,我想从原始记录中获取基于ParentId的新ParentId值。

            // here is the Records List After Cloning ClonedRecords
            //    Id        ParentId
            //    ---       --------
            //     1         null 
            //     2          1 
            //     3         null 
            //     4          3 
iCMS 回答:在EF核心中克隆对象时如何正确获取父ID的新外键值 创建克隆 IdFactory 用法

1)如果没有可以通过其找到的某些参数,则无法添加父项。如果在添加之后,他中断了与旧List 的所有通信。

2)您可以一次添加整棵树。

3)您可以在复制期间临时绑定新纸和旧纸的ID。

下面的示例不准确,主要是逻辑。而且,您可以使用其他数组代替字典。

static List<Record> Clone(List<Record> records)
{
    //for temprary save old_new id relationships
    Dictionary<int,int> temp = new 

    var clone = new List<Record>();
    foreach(var item in records)
    {
        var objtemp = new Record {
           Title = item.Title,};

        var rel = temp[x.item.ParentId];
        if(rel != null)
        {
            objtemp.ParentId = rel;
        }

        clone.Add(objtemp);
        //if id is sql identity you need savechanges()
        context.SaveChanges();

        temp.Add(item.id,clone.Id);
    }
}
,

因此,您希望克隆列表中的记录具有与原始列表中的值之一相似的所有值,但ID除外。您需要一个新的唯一ID,该ID在原始列表中没有使用。

简短回答

public ICollection<Record> Clone(IEnumerable<Record> originals,IIdFactory idFactory)
{
    // First create a new Id for every original Record.
    // Put them in a dictionary for fast lookup
    IDictionary<int,int> idTranslator = originals.ToDictionary(
       record => record.Id
       record => this.IdFactory.CreateId());

    return originals.Select(original => new Record
    {
        Id = idTranslator[original.Id],ParentId = idTranslator[original.ParentId],... // other properties
    })
    .ToList();
}

说明

每个克隆都需要一个适当的唯一新ID。因此,我们的方法需要一些东西来生成唯一的ID。

首先让我们为IdFactory定义一个接口:

interface IIdFactory
{
    int CreateId();
}

每次调用“创建”时,都会创建一个新的唯一ID。 参见下面的简单IdFactory

创建克隆

public ICollection<Record> Clone(IEnumerable<Record> originals,IIdFactory idFactory)
{
    // todo: decide what to do if originals == null

    // Before cloning,create a new Id for every clone
    // Put them in a dictionary for fast lookup
    IDictionary<int,int> idTranslator = originals.ToDictionary(
       record => record.Id
       record => this.IdFactory.CreateId());

因此,我们有一个字典,其中的键是原始文件中使用的所有ID,而值是相应克隆的ID。

开始克隆;使用idTranslator将原始ID转换为克隆ID:

return originals.Select(original => new Record
{
    Id = idTranslator[original.Id],... // other properties
})
.ToList();

确保将结果作为列表而不是作为IEnumerable返回,毕竟,您将丢失字典,因此返回后将无法再使用它。

IdFactory

我不知道您如何创建自己的ID,一个简单的工厂可能是:

class IdFactory : IIdFactory
{
    public IdFactory(IEnumerable<int> existingIds)
    {
        if (existingIds.Any())
        {
            this.nextId = existingIds.Max()+1;
        }
    }

    private int nextId = 0;

    public int CreateId()
    {
        int id = this.nextId;
        ++nextId;
        return id;
    }
}

但是您当然可以使用自己的IdFactory。

用法

IEnumerable<Record> originals = ...
IIdFactory idFactory = new IdFactory(originals);    
var clones = Clone(originals,idFactory);
本文链接:https://www.f2er.com/2294168.html

大家都在问