Я выбираю из базы данных список объектов примерно такой структуры:
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;:
Прикрепление сущности типа 'Project.Business.Entities.ProjectEntryType' не удалось, поскольку другая сущность того же типа уже имеет такое же значение первичного ключа.Это может произойти при использовании метода «Присоединить» или установке состояния объекта на «Неизменен» или «Изменен», если какие-либо объекты в графе имеют конфликтующие значения ключей.Это может быть потому, что некоторые объекты являются новыми и еще не получили сгенерированные базой данных значения ключей.В этом случае используйте метод «Добавить» или состояние добавленной сущности для отслеживания графика, а затем установите для состояния не новых сущностей значение «Неизмененные» или «Измененные» в зависимости от ситуации.
Если я изменю EntityState.Unchanged on EntityState.Detached Я получаю в db.SaveChanges (); Ошибка: нарушение ограничения PRIMARY KEY 'PK_ProjectEntryType'.Невозможно вставить дубликат ключа в объект 'dbo.ProjectEntryType'.Значение дубликата ключа (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 . * 1054 Iзаписывать с EF только те объекты, которые я указываю как измененные?