Come dice il titolo, posso aggiungere e aggiornare, ma quando si tratta di cancellare ottengo un errore.
L'operazione non è riuscita: la relazione non può essere modificata perché una o più proprietà della chiave esterna non sono annullabili. Quando viene apportata una modifica a una relazione, la relativa proprietà della chiave esterna viene impostata su un valore nullo. Se la chiave esterna non supporta valori nulli, deve essere definita una nuova relazione, la proprietà chiave esterna deve essere assegnata a un altro valore non nullo o l'oggetto non correlato deve essere eliminato.
Capisco che la Description
in questo caso ottiene solo una chiave esterna nullo ma non viene mai cancellata. Ho visto alcuni esempi in cui suggeriscono di scorrere ogni elemento figlio e cancellarli uno per uno. Imao penso che ci dovrebbe essere un modo migliore. Quello che sto cercando è una soluzione con un impatto minimo e basta dire a EF di cancellare l'intero elemento e non solo annullare la chiave esterna.
https://stackoverflow.com/a/5540956/3850405
Utilizzo di AutoMapper, AutoMapper.Collection e AutoMapper.Collection.EntityFramework.
Metodo di controllo:
public async Task<IHttpActionResult> UpdateArticle(ArticleViewModel articleVm)
{
Article articleOriginal = await iArticleRepository.GetAsync(articleVm.Id);
Article updatedArticle = Mapper.Map<ArticleViewModel, Article>(articleVm, articleOriginal);
await iArticleRepository.UpdateAsync(updatedArticle);
return Ok();
}
Mappatura:
Mapper.Initialize(cfg =>
{
cfg.AddCollectionMappers();
cfg.SetGeneratePropertyMaps<GenerateEntityFrameworkPrimaryKeyPropertyMaps<DbContext>>();
cfg.CreateMap<ArticleViewModel, Article>(MemberList.Source)
.EqualityComparison((src, dst) => src.Id == dst.Id);
cfg.CreateMap<DescriptionViewModel, Description>(MemberList.Source)
.EqualityComparison((src, dst) => src.Id == dst.Id);
}
Mapper.AssertConfigurationIsValid();
ViewModels:
public class ArticleViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<DescriptionViewModel> Descriptions { get; set; }
}
public class DescriptionViewModel
{
public int Id { get; set; }
public string Heading { get; set; }
}
Modelli:
public class Article : IEntity<int>
{
public Article()
{
Descriptions = new List<Description>();
}
[Key]
public int Id { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
[MaxLength(256)]
public string Name { get; set; }
public virtual ICollection<Description> Descriptions { get; set; }
}
public class Description: IEntity<int>
{
[Key]
public int Id { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
[MaxLength(256)]
public string Heading { get; set; }
public int ArticleId { get; set; }
public virtual Article Article { get; set; }
}
Ho una soluzione da questa risposta
https://stackoverflow.com/a/32983252/3850405
e questo blog:
http://www.kianryan.co.uk/2013/03/orphaned-child/
Codice:
public class Description: IEntity<int>
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
[MaxLength(256)]
public string Heading { get; set; }
[Key, Column(Order = 1)]
public int ArticleId { get; set; }
public virtual Article Article { get; set; }
}
Posso davvero raccomandare di leggere la risposta di Mosh sulla differenza tra composizione e aggregazione in quanto ti aiuterà a capire meglio EF.