EF Core - 无法向已存在相关对象的实体中添加实体

3
我正在将应用程序从EF 6迁移到EF Core 2.2。我有一个包含一些相关对象的对象,每个对象都有数据库生成的ID和GUID(数据库 - PostgreSQL)。
我正在尝试创建一个通用方法,以与EF 6相同的方式添加整个对象图及其所有相关对象 - 就像这样:
var res = context.Set<T>().Add(entity);

在插入之前,EF会创建临时ID,这些ID将被真实的数据库ID替换。
因此,在不同对象中,我可能会有完全相同的对象(为了更好的理解,我的主题领域是医学,我有几个不同的分析是从同一样本进行的),在EF Core中,我不能像这样添加整个对象图形 - 会收到错误消息,例如:
“Key(“ID”)=(5)已经存在”
但在EF6版本中,所有对象都可以被插入,包括具有正确ID和GUID的内部对象,没有重复项。
在两个版本中,同一对象中的临时ID也是相等的,但只有在EF Core版本中,我才会遇到这个错误。
我尝试了添加属性。
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

尝试更改DbContext

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

但是对我都不起作用 - 我认为问题并不在这里。

此外,我在Microsoft文档中找到了这篇文章,其中提到:

如果图表中包含重复项,则需要在将其发送到EF之前处理图表,以将多个实例合并为一个。

但我不确定 - 这是否与我的情况有关?

我做错了吗,还是在EF Core 2.2中不可能实现这一点?


我和你一起陷入了这个噩梦。你解决了吗? - CarComp
@CarComp,很遗憾没有。 - embolshov
我想通了...解决方案是不要保存那种类型的对象! :) - CarComp
1个回答

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;
    }

1
如果(e.Entry.Entity 是 IStaticObject 接口) - Jeremy Lakeman
哦,我明白了。我只是使用了包含(contains)函数。我还没有完全相信Is在数组上的使用。 - CarComp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接