我有如下表结构,如图所示。 (见:Table structure)。两个表("批次"和"方法")引用了一个"项目"表。
当我现在创建一个新项目时,我想创建所有孩子。
这样做我做了以下几点:
_dbContext.Projects.Where(x => x.Id == prjId)
.Include(x => x.Batches)
.Include(x => x.Batches.Select(y => y.Measurements))
.Include(x => x.Methods).AsNoTracking().FirstOrDefault();
现在问题如下:
创建新的批处理和方法实例 - 因此它们获得新的ID(PK)。引用的Project_Id(FK)设置正确。但在我的新Measurement实例中,只有Batch_Id(FK)设置正确且Method_Id保持不变(具有旧值)(参见:result)。
我需要的是Measurements.Mehtod_Id是从Methods表中设置的。
有没有合适的解决方案呢?
我的实体如下所示
public class Project
{
[Key]
public long Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public virtual List<Batch> Batches { get; set; }
public virtual List<Method> Methods { get; set; }
}
public class Batch : BaseObject
{
public Batch()
{
BatchFiles = new List<FileAttachment>();
Measurements = new List<Measurement>();
}
public long Id { get; protected set; }
public long Project_Id { get; set; }
public virtual Project Project { get; set; }
public virtual List<Measurement> Measurements { get; set; }
}
public class Method : BaseObject
{
public Method()
{
Parameters = new List<Parameter>();
}
public long Id { get; protected set; }
public long Project_Id { get; set; }
public virtual Project Project { get; set; }
public virtual List<Measurement> Measurements { get; set; }
}
public class Measurement
{
public int Id { get; protected set; }
[ForeignKey("Batch")]
public long? Batch_Id { get; set; }
[Required]
public virtual Batch Batch { get; set; }
[ForeignKey("Method")]
public long? Method_Id { get; set; }
public virtual Method Method { get; set; }
}
// creation code (just a copy with new IDs for all childs)
Project newProjectVersion = _dbContext.Projects.Where(x => x.Id == prjId)
.Include(x => x.Batches)
.Include(x => x.Batches.Select(y => y.Measurements))
.Include(x => x.Methods)
.AsNoTracking().FirstOrDefault();
_dbContext.Projects.Add(newProjectVersion);
_dbContext.SaveChanges();
感谢您的帮助!
答案 0 :(得分:1)
第一个问题是,由于Select
添加,您的Measurement
语句未将Method
与AsNoTracking()
连接起来。只有Project
和Method
已连接,因为它们明确Included
实体Project
。 Measurement
有一个Method_id
,但这个值在Method
属性中没有Method
。您可以在调试器中检查是否遍历对象图(尽管延迟加载已禁用!)。因此,当所有实体都Add
- 上下文时,EF不会注意到测量结果会接收新方法。
Include
现在您将看到Measurement.Method
将在对象图中的任何位置填充。
然而,这里有一个问题。使用...
.Include(x => x.Batches.Select(y => y.Measurements.Select(m => m.Method)))
...
时,EF6不会跟踪它实现的实体(duh)。这意味着,对于每个Measurement.Method
,它会创建一个新的AsNoTracking
实例,即使之前为另一个Measurement
实现了相同的Method
(按id)。 (在这种情况下,它将始终具有重复项,因为您已经包含Method
。)
这就是为什么您无法使用{1}}和Measurement
使用一个上下文实例快速执行此操作的原因。您将收到EF尝试附加重复实体的错误。
您必须使用一个上下文构建对象图,并进行跟踪,因此EF不会实现重复项。然后,您必须Project.Methods
此对象图表到新的上下文。看起来像这样:
AsNoTracking
三条评论:
Add
。通过将它们包含在Add
和现在(因为跟踪,并假设测量只包含它们所属的项目的方法)来加载所有方法,EF将它们与Project project;
using(var db = new MyContext())
{
db.Configuration.ProxyCreationEnabled = false;
project = db.Projects.Where(x => x.Id == prjId)
.Include(x => x.Batches)
.Include(x => x.Batches.Select(y => y.Measurements))
.Include(x => x.Methods).FirstOrDefault();
}
using(var db = new MyContext())
{
db.Projects.Add(project);
db.SaveChages();
}
s连接起来< em> relationship fixup 。Measurement.Method
时,它不会跟踪物化实体,但仍然不会创建重复项。在构建对象图时,似乎有一些临时跟踪。答案 1 :(得分:0)
[Required]
public virtual MeasurementType MeasurementType { get; set; }
[ForeignKey("MeasurementType")]
public long MeasurementType_Id { get; set; }
与批次和方法相比,不得复制这些条目,并且条目已存在于MeasrementTypes表中。 将所需的参考文献放入测量值的好方法是什么?