我从数据库中选择了大约这个结构的对象列表:
public static List<ProjectHeader> GetProjectHeadersWithEntries(int ProjectId)
{
using (var db = new ProjectContext(GlobalVariables.DBConnection))
{
var headers = db.ProjectHeaders.Where(x => x.ProjectId == ProjectId)
.Include(x => x.ProjectRun)
.Include(x => x.ProjectDeductionEntries)
.Include("ProjectDeductionEntries.EmployeeDeduction")
.Include("ProjectDeductionEntries.ProjectEntryType")
.Include(x => x.ProjectEarningEntries)
.Include("ProjectEarningEntries.ProjectEntryType")
.Include("ProjectEarningEntries.Department")
.Include(x => x.ProjectTaxEntries)
.Include("ProjectTaxEntries.ProjectEntryType")
.Include(x => x.Employee);
return headers.ToList();
}
}
然后从这个列表中我获取某个对象并在那里进行计算,例如:
-ProjectHeader CurrentHeader = _ProjectHeaders.FirstOrDefault();
-CurrentHeader.ProjectTaxEntries - 分配了所有新对象,因为需要删除旧对象并且必须写入新对象。
-CurrentHeader.ProjectDeductionEntries - 更改现有对象。
-CurrentHeader.ProjectEarningEntries - 更改现有对象。
我怎么能写CurrentHeader完全进入数据库,只是我希望这些变化,即不会有覆盖CurrentHeader.ProjectRun,CurrentHeader.ProjectDeductionEntries.ProjectEntryType,CurrentHeader.ProjectTaxEntries.ProjectEntryType ...
这是我的录音功能和我的评论。我想这样做来创建一个全新的对象:
public static ProjectHeader SaveProjectHeaderWithEntries(ProjectHeader header)
{
using (var db = new ProjectContext(GlobalVariables.DBConnection))
{
db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;
var oldTaxes = db.ProjectTaxEntries.Where(x => x.ProjectHeaderId == header.ProjectHeaderId);
db.ProjectTaxEntries.RemoveRange(oldTaxes);
db.SaveChanges();
foreach (var item in header.ProjectTaxEntries)
{
//item.ProjectEntryType = null;
//item.ProjectRun = null;
//db.ProjectTaxEntries.AddOrUpdate(item);`
if (item.ProjectEntryType != null)
db.Entry(item.ProjectEntryType).State = EntityState.Unchanged;
if (item.ProjectRun != null)
db.Entry(item.ProjectRun).State = EntityState.Unchanged;
if (item.ProjectTaxEntryId == 0)
{
db.Entry(item).State = EntityState.Added;
}
else
{
db.Entry(item).State = EntityState.Modified;
}
}
//header.ProjectTaxEntries = null;
//db.SaveChanges();
//db.Entry(header.ProjectRun).State = EntityState.Unchanged;
//db.Entry(header.Company).State = EntityState.Unchanged;
//db.Entry(header.Employee).State = EntityState.Unchanged;
foreach (var item in header.ProjectDeductionEntries)
{
//db.ProjectDeductionEntries.AddOrUpdate(item);
//db.ProjectDeductionEntries.Attach(item);
if (item.EmployeeDeduction != null)
db.Entry(item.EmployeeDeduction).State = EntityState.Unchanged;
if (item.ProjectEntryType != null)
db.Entry(item.ProjectEntryType).State = EntityState.Unchanged;
if (item.ProjectRun != null)
db.Entry(item.ProjectRun).State = EntityState.Unchanged;
if (item.ProjectDeductionEntryId == 0)
{
db.Entry(item).State = EntityState.Added;
}
else
{
db.Entry(item).State = EntityState.Modified;
}
}
foreach (var item in header.ProjectEarningEntries)
{
//db.ProjectEarningEntries.AddOrUpdate(item);
//db.ProjectEarningEntries.Attach(item);
if (item.ProjectEntryType != null)
db.Entry(item.ProjectEntryType).State = EntityState.Unchanged;
if (item.Employee != null)
db.Entry(item.Employee).State = EntityState.Unchanged;
if (item.ProjectRun != null)
db.Entry(item.ProjectRun).State = EntityState.Unchanged;
if (item.CompanyLocation != null)
db.Entry(item.CompanyLocation).State = EntityState.Unchanged;
if (item.Department != null)
db.Entry(item.Department).State = EntityState.Unchanged;
if (item.JobCode != null)
db.Entry(item.JobCode).State = EntityState.Unchanged;
if (item.ProjectEarningEntryId == 0)
{
db.Entry(item).State = EntityState.Added;
}
else
{
db.Entry(item).State = EntityState.Modified;
}
}
if (header.Company != null)
db.Entry(header.Company).State = EntityState.Unchanged;
if (header.Employee != null)
db.Entry(header.Employee).State = EntityState.Unchanged;
if (header.ProjectRun != null)
db.Entry(header.ProjectRun).State = EntityState.Unchanged;
if (header.ProjectHeaderId != 0)
{
db.Entry(header).State = EntityState.Modified;
}
else
{
db.Entry(header).State = EntityState.Added;
}
db.SaveChanges();
db.Configuration.AutoDetectChangesEnabled = true;
db.Configuration.ValidateOnSaveEnabled = true;
return GetProjectHeaderWithEntries(header.ProjectHeaderId);
}
}
在这个版本中,我在行 db.Entry(item.EmployeeDeduction)上收到错误.State = EntityState.Unchanged; :
附加&#39; Project.Business.Entities.ProjectEntryType&#39;类型的实体。失败,因为同一类型的另一个实体已具有相同的主键值。使用&#39;附加&#39;方法或将实体的状态设置为“未更改”#39;或者&#39;修改&#39;如果图中的任何实体具有冲突的键值。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,请使用&#39;添加&#39;方法或“添加”#39;实体状态跟踪图形,然后将非新实体的状态设置为“未更改”。或者&#39;修改&#39;酌情。
如果我在 EntityState.Detached 上更改 EntityState.Unchanged ,我会在 db.SaveChanges(); 错误中收到: 违反PRIMARY KEY约束&#39; PK_ProjectEntryType&#39;。无法在对象&#39; dbo.ProjectEntryType&#39;中插入重复键。重复键值为(200)。 声明已经终止。
EF希望在 ProjectEntryType 表中创建一个新条目,尽管我已将 EntityState.Detached 放在任何地方。 部分帮助在开始时做出记录:
foreach (var item in header.ProjectTaxEntries)
{
item.ProjectEntryType = null;
item.ProjectRun = null;
db.ProjectTaxEntries.AddOrUpdate(item);
}
db.SaveChanges();
但是,在视图中的 _ProjectHeaders 对象列表中, ProjectEntryType 和 ProjectRun 会丢失。在ProjectHeaders ProjectDeductionEntries.ProjectEntryType , ProjectEarningEntries.ProjectEntryType 和 ProjectTaxEntries.ProjectEntryType == null 。
如何使用EF仅记录我指定为Modified的对象?