简体   繁体   English

实体框架在插入子项后不保存导航属性

[英]Entity Framework not saving navigation properties after child insertion

I have two related entities, an incident and a reports (One to Many).我有两个相关实体,一个事件和一个报告(一对多)。 The incident will always be added first.事件将始终首先添加。 The reports will be added after the incident has been added, but never at the same time.报告将在添加事件后添加,但不会同时添加。 The report change tracking entity shows correct navigational relations after insertion.报告更改跟踪实体在插入后显示正确的导航关系。 But when I load the report or incident again, there is no relationship stored.但是当我再次加载报告或事件时,没有存储任何关系。

Any idea what I am doing wrong or missing?知道我做错了什么或错过了什么吗?

The incident model class (shortened):事件model class(简称):

public class Incident
{         
    public int Id { get; private set; }              
    public byte[] RowVersion { get; private set; }        
    public string UniqueId { get; set; }
    public ICollection<Report> Reports { get; private set; } = new HashSet<Report>();         
}

The report model class (shortened):报告 model class(简称):

public class Report
{ 
    public int Id { get; private set; }              
    public byte[] RowVersion { get; private set; }         
    public Incident Incident { get; set; }
    public string UniqueId { get; set; }
}

The incident configuration:事件配置:

internal class IncidentConfiguration : IEntityTypeConfiguration<Incident>
{
    internal static IncidentConfiguration Create() => new IncidentConfiguration();
    public void Configure(EntityTypeBuilder<Incident> builder)
    {
        builder
            .Property(incident => incident.Id)
            .ValueGeneratedOnAdd();
        builder
            .Property(incident => incident.RowVersion)
            .IsConcurrencyToken();
    }
}

The report configuration:报表配置:

internal class ReportConfiguration : IEntityTypeConfiguration<Report>
{
    internal static ReportConfiguration Create() => new ReportConfiguration();
    public void Configure(EntityTypeBuilder<Report> builder)
    {
        builder
            .Property(report => report.Id)
            .ValueGeneratedOnAdd();
        builder
            .Property(report => report.RowVersion)
            .IsConcurrencyToken();            
        builder
            .HasOne(report => report.Incident)
            .WithMany(incident => incident.Reports)
            .HasForeignKey(report => report.UniqueId)
            .HasPrincipalKey(incident => incident.UniqueId)
            .OnDelete(DeleteBehavior.Cascade);
    }
}

The method to add an incident:添加事件的方法:

public async ValueTask<EntityEntry<Common.Models.Incident>> AddAsync(Common.Models.Incident incident)
    {
        EntityEntry<Common.Models.Incident> entity = null;
        _manualResetEvent.WaitOne();
        try
        {
            using var context = new IncidentManagerContext(_connectionString);
            entity = await context.Incidents.AddAsync(incident);
            await context.SaveChangesAsync();
        }
        catch (Exception) { entity = null; }
        finally { _manualResetEvent.Set(); }
        return entity;
    }

The method to add a report:添加报表的方法:

public async ValueTask<EntityEntry<Common.Models.Report>> AddAsync(Common.Models.Report report)
    {
        EntityEntry<Common.Models.Report> entity = null;
        if (!string.IsNullOrEmpty(report.UniqueId))
        {
            _manualResetEvent.WaitOne();
            try
            {
                using var context = new IncidentManagerContext(_connectionString);
                entity = await context.AddAsync(report);
                await context.SaveChangesAsync();
            }
            catch (Exception) { entity = null; }
            finally { _manualResetEvent.Set(); }
        }
        return entity;
    }

Finally I found the issue, it wasn't that async stuff, neither the missing manual assignmet.最后我发现了问题,不是异步的东西,也不是缺少的手动分配。 It were simply the missing extension methods Include and ThenInclude on the loading side...这只是加载端缺少的扩展方法IncludeThenInclude ......

public async Task<Common.Models.Incident> GetByUniqueIdAsync(string uniqueId)
    {
        Common.Models.Incident incident = null;
        _manualResetEvent.WaitOne();
        try
        {
            using var context = new IncidentManagerContext(_connectionString);
            incident = await context.Incidents
                .Include(incident => incident.Reports)
                .ThenInclude(reports => reports.DetailReports)
                .Where(i => i.UniqueId == uniqueId)
                .SingleAsync();
        }
        catch (Exception) { }
        finally { _manualResetEvent.Set(); }
        return incident;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM