EF Core-无法添加具有相同相关对象的实体

时间:2019-07-30 08:28:23

标签: c# postgresql entity-framework entity-framework-core

我正在将应用程序从EF 6移植到EF Core 2.2。我有一个对象,里面有一些相关的对象,每个对象都有数据库生成的ID和GUID(db-postgresql)。

我正在尝试创建一种通用方法,以与EF 6中相同的方式添加具有所有相关对象的整个对象图-像这样:

var res = context.Set<T>().Add(entity);

在插入之前,EF会创建临时ID,这些ID将被实际的数据库ID取代。

因此,因为在不同的对象内,我可能具有完全相同的对象(为了更好地理解,我的学科领域是医学,所以我对同一样本执行了几种不同的分析),因此在EF Core中,我无法添加全部这样的对象图-出现错误,例如:

  

键(\“ ID \”)=(5)已经存在

但是在EF 6版本中,一切正常工作-插入了所有对象,包括具有正确ID和GUID的内部对象,没有重复项。

在这两个版本中,同一对象中的临时ID也相等,但仅在EF Core版本中,出现此错误。

我尝试添加属性

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

试图更改DbContext

modelBuilder.Entity<Sample>().Property(e => e.ID).ValueGeneratedOnAdd();

但都不适合我-我认为问题不在这里。

我还在Microsoft文档中找到了this文章,内容为

  

如果该图确实包含重复项,则有必要在将该图发送到EF之前将其合并为一个实例。

但我不确定-这是我的案子吗?

我做错了吗?或者在EF Core 2.2中是不可能的?

1 个答案:

答案 0 :(得分:0)

魔术酱:创建一个接口并在您不想保存在对象图上的对象上实现,然后简单地不要将该对象设置为已修改。我无法理解的范例是,在使用该对象定义要保存的对象时,我从来没有真正想要保存过“定义”对象。

我用一个单独的过程保存定义对象。完美运行。

public virtual T InsertOrUpdate(T oneObject)
    {
        T output = null;

        if (oneObject.Id == Guid.Empty)
        {
            output = this.Insert(oneObject);
        }
        else
        {
            try
            {
               
                _dbContext.ChangeTracker.TrackGraph(oneObject, e =>
                {
                    if (e.Entry.IsKeySet)
                    {
                        // See if the entry has interface with 'StaticObject'
                        List<Type> x = e.Entry.Entity.GetType().GetInterfaces().ToList();
                        
                        if (x.Contains(typeof(IStaticObject)))
                        {
                            _logger.LogWarning($"Not tracking entry {e.Entry}");
                        }
                        else
                        {
                            e.Entry.State = EntityState.Modified;
                        }
                    }
                    else
                    {
                        e.Entry.State = EntityState.Added;
                    }

                });

                _dbContext.Entry(oneObject).State = EntityState.Modified;

                _dbContext.SaveChanges();
                
                output = oneObject;
                
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Problem updating object {oneObject.Id}");
            }
        }

        return output;
    }
    
public virtual T Insert(T oneObject)
    {
        try
        {
            _dbContext.Attach(oneObject);
            _dbContext.Entry(oneObject);
            _dbContext.SaveChanges();
        }
        catch (Exception error)
        {
            _logger.LogError(error.Message, error);
        }

        return oneObject;
    }