Open lsymds opened 8 months ago
Notes for triage: I spent a bit more (too much) time investigating this further. With a few tweaks to allow constructor configuration, the following works:
modelBuilder.Entity<Foo>().ComplexProperty(
e => e.Date, b =>
{
var timeProperty = b.Property(e => e.UtcDateTime).HasField("_dateTime").Metadata;
var offsetProperty = b.Property<short>("_offsetMinutes").Metadata;
var complexType = (ComplexType)b.Metadata.ComplexType;
complexType.ConstructorBinding = new ConstructorBinding(
typeof(DateTimeOffset)
.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)
.Single(
c =>
{
var parameters = c.GetParameters();
return parameters.Length == 2
&& parameters[0].Name == "validOffsetMinutes"
&& parameters[1].Name == "validDateTime";
}),
new[]
{
new PropertyParameterBinding((IProperty)offsetProperty),
new PropertyParameterBinding((IProperty)timeProperty)
});
});
Whether or not this is a good idea, since:
DateTimeOffset
DateTimeOffset
is primitive in our code, which could cause issues when doing thisStill, it's cool we can do this. :-)
Full code here: https://github.com/dotnet/efcore/tree/240118_NotSoSimpleAfterAll
Overview
Whilst messing around with complex types in an attempt to persist a
DateTimeOffset
as two separate columns (one containing the ticks, and another containing the offset ticks), I received an error telling me the following:System.ArgumentException: The specified type 'System.DateTimeOffset' must be a non-interface type with a public constructor to be used as a complex type.
DateTimeOffset
is not an interface type AND has a public constructor available to be used, so I assumed it was something else.After delving into the
ComplexType
constructor, and subsequently theSharedTypeExtensions.IsValidComplexType
extension method, I noticed that there is a check that identifies whether the provided type is a scalar type (whichDateTimeOffset
is). The thrown exception's message does not indicate this, and, although an unlikely occurrence, probably should?Repro steps
Steps
DateTimeOffset
(or another scalar type) as a complex property on a model.Code
System Information
EF Core version: 8.0.0 Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer) Microsoft.EntityFrameworkCore.Sqlite Target framework: (e.g. .NET 6.0) .NET 8.0 Operating system: Windows 11 IDE: (e.g. Visual Studio 2022 17.4) Jetbrains Rider 2023.3