Reputation: 5227
So my entity has two properties with an owned entity. For some reason EF Core is adding a discriminator column to one of them. It would be great if someone could help me figure out what I'm doing wrong or if there is some weird bug here.
This is the whole entity even though I suspect only Requested
and Approved
is relevant.
public class Absence
{
public Absence()
{
Requested = new AuditInfo();
Approved = new AuditInfo();
}
public Guid Id { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public AbsenceType Type { get; set; }
public AbsenceState State { get; set; }
public AuditInfo Requested { get; set; }
public AuditInfo Approved { get; set; }
public Guid EmployeeId { get; set; }
public Employee Employee { get; set; }
public ICollection<AbsenceDay> Days { get; set; }
}
Absence
doesn't have any special mappings but AuditInfo is mapped as
x.Owned<AuditInfo>();
This mostly generate the expected SQL, except this weird item:
This also leads to the code failing at runtime with this message:
Message: Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while updating the entries. See the inner exception for details.
---- System.Data.SqlClient.SqlException : Cannot insert the value NULL into column 'ApprovedA_Discriminator', table 'bokio-test.dbo.Absences'; column does not allow nulls. INSERT fails.
The statement has been terminated.
What I have tried:
I tried mapping the items like this which makes no difference:
x.Entity<Absence>().OwnsOne(x1 => x1.Approved);
x.Entity<Absence>().OwnsOne(x1 => x1.Requested);
I tried renaming Approved
to ApprovedA
which made no difference.
I then tried a small repro like this which doesn't create a discriminator column:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public Address HomeAddress { get; set; }
public Address WorkAddress { get; set; }
}
Now I'm out of ideas and need some help.
Update 1:
Hold your hats, things are about to get really weird!
When I rename Approved
to Donkey
the discriminator column goes away 🤯
Almost stranger is that when I try to repro it with the name Approved in the small test I still don't get the discriminator column there.
Update 2:
So I tried a bunch of other names. Success means no discriminator column.
Xpproved = success App = fail Ap = fail CrAp = success A = fail Axx = success ApprovedXX = fail XApproved = success
That inspired me to try this solution with XApproved which works
x.Entity<Absence>().OwnsOne(x1 => x1.XApproved, o =>
{
o.Property(x2 => x2.Ip).HasColumnName("Approved_Ip");
o.Property(x2 => x2.UserAgent).HasColumnName("Approved_UserAgent");
o.Property(x2 => x2.UserId).HasColumnName("Approved_UserId");
o.Property(x2 => x2.TimeUtc).HasColumnName("Approved_TimeUtc");
});
Update 3:
AuditInfo only has these properties and no mappings beside being Owned
. It does have a bunch of classes inheriting it though:
public DateTime TimeUtc { get; set; }
public Guid? UserId { get; set; }
public string Ip { get; set; }
public string UserAgent { get; set; }
Upvotes: 3
Views: 2920
Reputation: 5227
While I don't fully understand the issue (why changing the name made the problem go away) I noticed that it didn't really solve the problem. But rather just moved it around. The comment comment from @philreed above was what really made it click.
AuditInfo
was inherited by another Owned Entity ClosurePart
. By changing from
public class AuditInfo {
...props here
}
public class ClosurePart : AuditInfo {}
to
public class AuditInfoCommon {
...props here
}
public class AuditInfo : AuditInfoCommon {}
public class ClosurePart : AuditInfoCommon {}
The problem went away fully without needing the hacks.
NOTE: AuditInfoCommon is not mapped into the model!
Upvotes: 2