Я занимаюсь разработкой ASP. NET Core + EF Core приложения.
Я немного (очень много) борюсь с методом обновления контроллера, который управляет наиболее сложным объект моего проекта.
Объект выглядит примерно так:
public class CIApplication : ConfigurationItem
{
public String InventoryCollectionQuery { get; set; }
public EnumCCMCIType CCMCIType { get; set; }
//Collection of DeploymentScenario
public virtual ICollection<DeploymentScenario> DeploymentScenarios { get; set; }
//Collection of SoftwareMeteringRules
public virtual ICollection<SoftwareMeteringRule> SoftwareMeteringRules { get; set; }
//Collection of AppLocalPresenceCondition
public virtual ICollection<AppLocalPresenceCondition> AppLocalPresenceConditions { get; set; }
}
И некоторые из объектов в коллекциях также могут содержать другие коллекции и так далее, и так далее ...
На самом деле мои методы обновления работают (что ниже), но это настоящая боль в поддержании, когда я делаю некоторые изменения в моей модели. Поскольку я разрабатывал это довольно давно, go мне интересно, есть ли лучший подход для этого. И, что лучше, для меня это намного проще :) иногда я даже задаюсь вопросом, не лучше ли удалить объект и воссоздать его.
var cIApplicationInDB = _context.CIApplications
.Include(c => c.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps).ThenInclude(s => s.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps).ThenInclude(s => s.InputVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallSteps).ThenInclude(s => s.OutPutVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps).ThenInclude(s => s.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps).ThenInclude(s => s.InputVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.UninstallSteps).ThenInclude(s => s.OutPutVariables).ThenInclude(x => x.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.Translations)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.DetectionMethods)
.Include(c => c.DeploymentScenarios).ThenInclude(d => d.InstallationBehaviorRules)
.Include(c => c.SoftwareMeteringRules)
.Include(c => c.Catalogs)
.Include(c => c.Categories)
.Include(c => c.OwnerCompany)
.Include(c => c.AppLocalPresenceConditions)
.SingleOrDefault(c => c.ID == id);
_context.Entry(cIApplicationInDB).CurrentValues.SetValues(cIApplication);
// Updating Translations
foreach (var upTodateTranslation in cIApplication.Translations)
{
var existingTranslation = cIApplicationInDB.Translations.FirstOrDefault(t => t.Id == upTodateTranslation.Id);
if (existingTranslation == null)
{
cIApplicationInDB.Translations.Add(upTodateTranslation);
}
else
{
_context.Entry(existingTranslation).CurrentValues.SetValues(upTodateTranslation);
}
}
foreach (var ExistingTranslation in cIApplicationInDB.Translations)
{
if (!cIApplication.Translations.Any(t => t.Id == ExistingTranslation.Id))
{
_context.Remove(ExistingTranslation);
}
}
// Updating SoftwareMeteringRules
foreach (var upTodateSoftwareMeteringRule in cIApplication.SoftwareMeteringRules)
{
var existingSoftwareMeteringRule = cIApplicationInDB.SoftwareMeteringRules.FirstOrDefault(t => t.ID == upTodateSoftwareMeteringRule.ID);
if (existingSoftwareMeteringRule == null)
{
cIApplicationInDB.SoftwareMeteringRules.Add(upTodateSoftwareMeteringRule);
}
else
{
_context.Entry(existingSoftwareMeteringRule).CurrentValues.SetValues(upTodateSoftwareMeteringRule);
}
}
foreach (var existingSoftwareMeteringRule in cIApplicationInDB.SoftwareMeteringRules)
{
if (!cIApplication.SoftwareMeteringRules.Any(t => t.ID == existingSoftwareMeteringRule.ID))
{
_context.Remove(existingSoftwareMeteringRule);
}
}
// Updating DeploymentScenarios Graph
foreach (var upToDateDS in cIApplication.DeploymentScenarios)
{
// Look for incoming DS into the actual db CI
var existingDeploymentScenario = cIApplicationInDB.DeploymentScenarios.FirstOrDefault(d => d.ID == upToDateDS.ID);
// can't find DS in existing CI, it is new
if (existingDeploymentScenario == null)
{
// cIApplicationInDB.DeploymentScenarios.
cIApplicationInDB.DeploymentScenarios.Add(upToDateDS);
}
// Look if there are things to update in existing DS
else
{
_context.Entry(existingDeploymentScenario).CurrentValues.SetValues(upToDateDS);
// update DeploymentScenario translations
....
...doing the same way for all objects
// and then after going through all sub collections :
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException e)
{
if (!CIApplicationExists(id))
{
return NotFound();
}
else
{
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}