C
C#12mo ago
Kuurama

EFCore 8 - Owned type with navigation property not being included

Hello, i have an issue with EFCore (or maybe it's just me being pepega), but i have a class Score that have a Tracker field as an owned type:
class Score {
[Key]
public uint ID {get; set;}
public bool HasTrackers { get; set; }

public Trackers Trackers { get; set; } = new Trackers() ;
}
class Score {
[Key]
public uint ID {get; set;}
public bool HasTrackers { get; set; }

public Trackers Trackers { get; set; } = new Trackers() ;
}
And here is the tracker class:
[Owned]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class Trackers
{
public HitTracker? HitTracker { get; set; } = null;
public WinTracker? WinTracker { get; set; } = null;
public AccuracyTracker? AccuracyTracker { get; set; } = null;
public ScoreGraphTracker? GraphTracker { get; set; } = null;
}
[Owned]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class Trackers
{
public HitTracker? HitTracker { get; set; } = null;
public WinTracker? WinTracker { get; set; } = null;
public AccuracyTracker? AccuracyTracker { get; set; } = null;
public ScoreGraphTracker? GraphTracker { get; set; } = null;
}
and lastly the HitTracker class:
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class HitTracker
{
[Required]
[Key]
[ForeignKey(nameof(Score))]
public uint ScoreID { get; set; }

public int MaxCombo { get; set; }
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class HitTracker
{
[Required]
[Key]
[ForeignKey(nameof(Score))]
public uint ScoreID { get; set; }

public int MaxCombo { get; set; }
}
(obvisouly i'm only sending what's usefull here, it's not the whole classes but it doesn't matter) My issue that that, when querying Context.RankedScore, including RankedScore.Score, then Score.Trackers.HitTracker, i'm not getting any trackers. nor if i include them all the way like this:
m_Context.RankedScores.Where(p_X => p_X.ID == id)
.AsNoTracking().Include(p_X => p_X.Score).ThenInclude(p_Y => p_Y.Trackers).ThenInclude(p_Tracker => p_Tracker.HitTracker);
m_Context.RankedScores.Where(p_X => p_X.ID == id)
.AsNoTracking().Include(p_X => p_X.Score).ThenInclude(p_Y => p_Y.Trackers).ThenInclude(p_Tracker => p_Tracker.HitTracker);
I don't know if i should use a Owned class to achieve this behavior, but i simply wanted to have the child perperties wrapped into an object called Trackers so it makes more sence in the backend and in the front end, instead of doing Score.HitTracker, Score.Trackers.HitTracker seems better to me. Does anyone know how to resolve my issue? I'm getting this (it should include the HitTracker, not null, it doesn't include any of them actually)
"hasTrackers": true,
"trackers": {
"hitTracker": null,
"winTracker": null,
"accuracyTracker": null,
"graphTracker": null
}
"hasTrackers": true,
"trackers": {
"hitTracker": null,
"winTracker": null,
"accuracyTracker": null,
"graphTracker": null
}
Here is the output as sql (just the interesting part):
FROM `RankedScores` AS `r`
INNER JOIN `Scores` AS `s` ON `r`.`ScoreID` = `s`.`ID`
LEFT JOIN `AccuracyTracker` AS `a` ON `s`.`Trackers_AccuracyTrackerScoreID` = `a`.`ScoreID`
WHERE `r`.`ID` = @__id_0
FROM `RankedScores` AS `r`
INNER JOIN `Scores` AS `s` ON `r`.`ScoreID` = `s`.`ID`
LEFT JOIN `AccuracyTracker` AS `a` ON `s`.`Trackers_AccuracyTrackerScoreID` = `a`.`ScoreID`
WHERE `r`.`ID` = @__id_0
No description
1 Reply
Kuurama
KuuramaOP12mo ago
THe navigation might be wrong, but it's auto generated so i don't know, i do the classes first:
modelBuilder.Entity("Server.Database.Models.Score", b =>
{
b.HasOne("Server.Database.Models.Player", "Player")
.WithMany("Scores")
.HasForeignKey("PlayerID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.HasOne("Server.Database.Models.SongDifficulty", "SongDifficulty")
.WithMany()
.HasForeignKey("SongDifficultyID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.OwnsOne("Server.Database.Models.Trackers", "Trackers", b1 =>
{
b1.Property<uint>("ScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("AccuracyTrackerScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("GraphTrackerScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("HitTrackerScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("WinTrackerScoreID")
.HasColumnType("int unsigned");

b1.HasKey("ScoreID");

b1.HasIndex("AccuracyTrackerScoreID");

b1.HasIndex("GraphTrackerScoreID");

b1.HasIndex("HitTrackerScoreID");

b1.HasIndex("WinTrackerScoreID");

b1.ToTable("Scores");

b1.HasOne("Server.Database.Models.AccuracyTracker", "AccuracyTracker")
.WithMany()
.HasForeignKey("AccuracyTrackerScoreID");

b1.HasOne("Server.Database.Models.ScoreGraphTracker", "GraphTracker")
.WithMany()
.HasForeignKey("GraphTrackerScoreID");

b1.HasOne("Server.Database.Models.HitTracker", "HitTracker")
.WithMany()
.HasForeignKey("HitTrackerScoreID");

b1.WithOwner()
.HasForeignKey("ScoreID");

b1.HasOne("Server.Database.Models.WinTracker", "WinTracker")
.WithMany()
.HasForeignKey("WinTrackerScoreID");

b1.Navigation("AccuracyTracker");

b1.Navigation("GraphTracker");

b1.Navigation("HitTracker");

b1.Navigation("WinTracker");
});

b.Navigation("Player");

b.Navigation("SongDifficulty");

b.Navigation("Trackers")
.IsRequired();
});
modelBuilder.Entity("Server.Database.Models.Score", b =>
{
b.HasOne("Server.Database.Models.Player", "Player")
.WithMany("Scores")
.HasForeignKey("PlayerID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.HasOne("Server.Database.Models.SongDifficulty", "SongDifficulty")
.WithMany()
.HasForeignKey("SongDifficultyID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.OwnsOne("Server.Database.Models.Trackers", "Trackers", b1 =>
{
b1.Property<uint>("ScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("AccuracyTrackerScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("GraphTrackerScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("HitTrackerScoreID")
.HasColumnType("int unsigned");

b1.Property<uint?>("WinTrackerScoreID")
.HasColumnType("int unsigned");

b1.HasKey("ScoreID");

b1.HasIndex("AccuracyTrackerScoreID");

b1.HasIndex("GraphTrackerScoreID");

b1.HasIndex("HitTrackerScoreID");

b1.HasIndex("WinTrackerScoreID");

b1.ToTable("Scores");

b1.HasOne("Server.Database.Models.AccuracyTracker", "AccuracyTracker")
.WithMany()
.HasForeignKey("AccuracyTrackerScoreID");

b1.HasOne("Server.Database.Models.ScoreGraphTracker", "GraphTracker")
.WithMany()
.HasForeignKey("GraphTrackerScoreID");

b1.HasOne("Server.Database.Models.HitTracker", "HitTracker")
.WithMany()
.HasForeignKey("HitTrackerScoreID");

b1.WithOwner()
.HasForeignKey("ScoreID");

b1.HasOne("Server.Database.Models.WinTracker", "WinTracker")
.WithMany()
.HasForeignKey("WinTrackerScoreID");

b1.Navigation("AccuracyTracker");

b1.Navigation("GraphTracker");

b1.Navigation("HitTracker");

b1.Navigation("WinTracker");
});

b.Navigation("Player");

b.Navigation("SongDifficulty");

b.Navigation("Trackers")
.IsRequired();
});
I just went Score.HitTracker, Score.AccuracyTracker, instead of wrapping them. Because i felt like this couldn't be helped without changing the onModelCreated, which i don't wznt to do. If you guys had an explaination i would still be up to understand it..
Want results from more Discord servers?
Add your server