我正在将应用程序从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中是不可能的?
答案 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;
}