且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将多个导航属性配置到同一表时出错

更新时间:2022-12-12 16:43:32

在您配置 EventReport FuelBunkerType 之间的两个一对一关系时,EF多方面的一个集合无法匹配这些关系.取决于集合属性 ActiveFuelTypes 所属的关系,您可以像这样明确地映射它:

  modelBuilder.Entity< FuelBunkerQuantity>().HasOptional(x => x.FuelBunkerType).WithMany(e => e.ActiveFuelTypes).HasForeignKey(x => x.IdFuelBunkerType); 

I am having a weird issue with multiple navigation Properties to the same table.

My FuelBunkerType POCO class is configured like the following:

    public class FuelBunkerType : IEventReportElement
{

    public long Id { get; set; }
    public string TypeKey { get; set; }        
    public string TypeValue { get; set; }
    public decimal? Sulphur { get; set; }
    public decimal? Water { get; set; }
    public decimal? Viscosity { get; set; }
    public decimal? Density { get; set; }
    public string BdnNumber { get; set; }
    public long? IdEventReport { get; set; }
    public long? DeactivatedByIdEventReport { get; set; }

    public IList<FuelBunkerQuantity> FuelBunkerQuantitys { get; set; }
    public EventReport EventReport { get; set; }
    public EventReport DeactivatedByEventReport { get; set; }
}

In the DbContext, my class is configured like:

    modelBuilder.Entity<FuelBunkerType>().HasKey(x => x.Id);
        if (_writeversion) modelBuilder.Entity<FuelBunkerType>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        else modelBuilder.Entity<FuelBunkerType>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<FuelBunkerType>().HasRequired(x => x.EventReport).WithMany().HasForeignKey(x => x.IdEventReport);
        modelBuilder.Entity<FuelBunkerType>().HasOptional(x => x.DeactivatedByEventReport).WithMany().HasForeignKey(x => x.DeactivatedByIdEventReport);

So far, so good. It actually worked like this until friday. However, when I try to fetch data from the table now, the resulting Query looks like

{SELECT 
1 AS [C1], 
[Extent1].[Id] AS [Id], 
[Extent1].[TypeKey] AS [TypeKey], 
[Extent1].[TypeValue] AS [TypeValue], 
[Extent1].[Sulphur] AS [Sulphur], 
[Extent1].[Water] AS [Water], 
[Extent1].[Viscosity] AS [Viscosity], 
[Extent1].[Density] AS [Density], 
[Extent1].[BdnNumber] AS [BdnNumber], 
[Extent1].[IdEventReport] AS [IdEventReport], 
[Extent1].[DeactivatedByIdEventReport] AS [DeactivatedByIdEventReport], 
[Extent1].[EventReport_Id] AS [EventReport_Id]
FROM [FuelBunkerType] AS [Extent1]}

which obviously results in a "column name is not valid" error, so my first Configuration line (Entity().HasRequired(x=>x.EventReport)...) is ignored. I tried out commenting out the Configuration for DeactivatedByEventReport, it resulted in the same query except for DeactivatedByEventReport_Id (like expected), it only happens with multiple Navigation Properties to the same table. However, when I add more navigation properties to EventReport, it only mistakenly queries for EventReport_Id, so only the first one seems to be ignored when there are multiple navigation properties.

Any ideas why this happens, and what to do to solve this? Greetings

EDIT: For the other classes corresponding to this, there are the following Fluent API configs:

if (_writeversion) modelBuilder.Entity<EventReport>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        else modelBuilder.Entity<EventReport>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<EventReport>().HasKey(x => x.Id);
        modelBuilder.Entity<EventReport>().Property(x => x.Id).HasColumnName("Id");
        modelBuilder.Entity<EventReport>().Ignore(x => x.MaxEventTimeLt);
        modelBuilder.Entity<EventReport>().Ignore(x => x.MaxEventTimeUtc);
        modelBuilder.Entity<EventReport>().Ignore(x => x.MinEventTimeLt);
        modelBuilder.Entity<EventReport>().Ignore(x => x.MinEventTimeUtc);
        modelBuilder.Entity<EventReport>().Ignore(x => x.EventReportElementTyps);
        modelBuilder.Entity<EventReport>().Ignore(x => x.EventsWithUpdatedSortNumber);
        modelBuilder.Entity<EventReport>().Ignore(x => x.EventTimeUtcLoaded);
        modelBuilder.Entity<EventReport>().Ignore(x => x.HasChanged);

      modelBuilder.Entity<FuelBunkerQuantity>().HasKey(x => x.Id);
        if (_writeversion) modelBuilder.Entity<FuelBunkerQuantity>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        else modelBuilder.Entity<FuelBunkerQuantity>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<FuelBunkerQuantity>().HasOptional(x => x.FuelBunkerType).WithMany().HasForeignKey(x => x.IdFuelBunkerType);
        //modelBuilder.Entity<FuelBunkerQuantity>().HasOptional(x => x.EventReport).WithMany().HasForeignKey(x => x.IdEventReport);
        modelBuilder.Entity<FuelBunkerQuantity>().Ignore(x => x.EventReport);

The Configs on EventReport shouldn't effect anything, as you can see I disabled the navigation property on FuelBunkerQuantity to try if this was causing the error, but it didn't change the Error or the resulting Query in the slightest.

EDIT2: The class EventReport:

public class EventReport
{
    public long Id { get; set; }


    public long? SortNumber { get; set; }
    public string ReportType { get; set; }
    public DateTime? CreationTimeUtc { get; set; }


    public DateTime? EventTimeUtc { get; set; }

    public DateTime? EventTimeUtcLoaded { get; set; }
    public DateTime? EventTimeLt { get; set; }
    public long? EventDuration { get; set; }
    public DateTime? LastSendAtUtc { get; set; }
    public DateTime? LastSendAtLt { get; set; }
    public DateTime? FirstSendAtUtc { get; set; }
    public DateTime? FirstSendAtLt { get; set; }
    public string EventQualityState { get; set; }
    public bool IsDraft { get; set; }

    [IgnoreOnEqualCheck]
    public IEnumerable<FuelBunkerRob> FuelRoB { get; set; }
    [IgnoreOnEqualCheck]
    public IEnumerable<OilBunkerRob> OilRoB { get; set; }
    [IgnoreOnEqualCheck]
    public List<FuelBunkerType> ActiveFuelTypes { get; set; }
    [IgnoreOnEqualCheck]
    public DateTime? MaxEventTimeUtc { get; set; }
    [IgnoreOnEqualCheck]
    public DateTime? MaxEventTimeLt { get; set; }
    [IgnoreOnEqualCheck]
    public DateTime? MinEventTimeUtc { get; set; }
    [IgnoreOnEqualCheck]
    public DateTime? MinEventTimeLt { get; set; }


    public List<EventReport> EventsWithUpdatedSortNumber {get; set;}


    public long? ConfigurationId { get; set; }


    public bool HasChanged { get; set; }
    public List<IEventReportElement> EventReportElements { get; set; }
}

EDIT3: I just skipped the Statement which was causing the error. Turns out FuelBunkerQuantity has wrong Translation as well (see configuration in Edit):

{SELECT 
1 AS [C1], 
[Extent1].[Id] AS [Id], 
[Extent1].[IdFuelBunkerType] AS [IdFuelBunkerType], 
[Extent1].[MassDelta] AS [MassDelta], 
[Extent1].[MassAbsolut] AS [MassAbsolut], 
[Extent1].[IdEventReport] AS [IdEventReport], 
[Extent1].[FuelBunkerType_Id] AS [FuelBunkerType_Id]
FROM [FuelBunkerQuantity] AS [Extent1]}

Seems like something is broken, but I have no idea what.

As you are configuring two one-to-may relationships between EventReport and FuelBunkerType and there is only one collection on the many side EF can't match the relationships. Depending on which relationship the collection property ActiveFuelTypes belongs to you can explicitly map it like this:

modelBuilder.Entity<FuelBunkerQuantity>().
             HasOptional(x => x.FuelBunkerType).
             WithMany(e => e.ActiveFuelTypes).
             HasForeignKey(x => x.IdFuelBunkerType);