簡體   English   中英

如何在 Entity Framework Core 中的父更新時從父集合中刪除子實體?

[英]How to remove child entities from parent collection on parent update in Entity Framework Core?

我有以下問題:當我嘗試更新問題並在關鍵字屬性中提供新關鍵字時,該關鍵字尚未與正確添加的問題相關。 假設有兩個關鍵字映射到問題。 然后我用一個與問題無關的關鍵字發送更新請求。 它導致問題被映射到三個關鍵字。 當我發送空的關鍵字列表時,沒有任何變化。 我希望發生的是當我發送一個關鍵字時 - 然后它只是與問題相關的這個關鍵字,其余的被刪除。 我怎樣才能實現以下目標? 我已經嘗試在關鍵字的配置方法中添加“QuestionKeyword”段,但它並沒有太大變化。 另外發生的情況是關鍵字正在從 C# 應用程序內的實體中刪除,但是當我添加一個虛擬代碼行時,再次從上下文中獲取相同的問題,然后在調用 Include() 后再次加載它的問題 - 因為它們從來沒有刪除。

考慮下面的代碼:

public class Keyword
{
        public string Name { get; set; }
        public List<Question> Questions { get; set; }
}

public class Question : AuditableEntity
{
        public int Id { get; set; }
        public string Content { get; set; }
        public string Answer { get; set; }
        public int Rating { get; set; } 
        public IList<Keyword> Keywords { get; set; } = new List<Keyword>(); 
}

這些實體按以下方式配置:

public void Configure(EntityTypeBuilder<Keyword> builder)
{
        builder.Ignore(entity => entity.DomainEvents);
        builder.HasKey(entity => entity.Name);

        builder.HasMany(entity => entity.Questions)
            .WithMany(entity => entity.Keywords)
            .UsingEntity<Dictionary<string, object>>(
                       "QuestionKeyword",
                       j => j.HasOne<Question>().WithMany().OnDelete(DeleteBehavior.Cascade),
                       j => j.HasOne<Keyword>().WithMany().OnDelete(DeleteBehavior.Cascade));
 } 


public void Configure(EntityTypeBuilder<Question> builder)
{ 
        builder.HasKey(entity => entity.Id);
}

這是更新問題的業務邏輯:

public async Task<Unit> Handle(UpdateQuestionCommand request, CancellationToken cancellationToken)
{
        Question question = await _context.Questions.Include(q => q.Keywords).AsNoTracking().SingleOrDefaultAsync(q => q.Id == request.Id, cancellationToken);
        if (question == null)
            throw new NotFoundException($"Id = {request.Id}");

        _context.Keywords.RemoveRange(question.Keywords);

        QuestionDto questionDto = _mapper.Map<QuestionDto>(question);
                request.PatchDocument.ApplyTo(questionDto);

        QuestionDtoValidator validator = new QuestionDtoValidator();
        ValidationResult result = validator.Validate(questionDto);

        if (!result.IsValid)
        {
            throw new CustomValidationException(result.Errors);    
        }
        question = _mapper.Map<Question>(questionDto);
        _context.Questions.Update(question);
        
        question.DomainEvents.Add(new QuestionUpdatedEvent(question));
        await _context.SaveChangesAsync(cancellationToken);
        return Unit.Value;
}

您必須清除問題的所有關鍵字,然后將新關鍵字添加到您的問題中,如下所示:

Question question = await _context.Questions.Include(q => q.Keywords).SingleOrDefaultAsync(q => q.Id == request.Id, cancellationToken);

question.Keywords.Clear();

....

但請注意AsNoTracking()已被刪除!

使用AsNoTracking()意味着獲取的對象更改對您來說無關緊要,EF 將忽略更改!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM