我有一个采用 TPH 策略的表,该策略将许多衍生类型映射到同一个表(这里没有什么不寻常的)。
我使用未映射的类型(未在 EDM 中声明)与原始 SQL(通过
SqlQuery
)结合使用来自基本类型和派生类型的 SELECT
属性(列)。
实体:
public class Base
{
public Guid Id { get; set; }
public DateTimeOffset Created { get; set; }
}
public class A : Base
{
public string AProperty { get; set; }
}
public class B : Base
{
public string BProperty { get; set; }
}
未映射类型:
public class Model
{
public Guid Id { get; set; }
public string AProperty { get; set; }
public string BProperty { get; set; }
public DateTimeOffset Created { get; set; }
}
查询:
var models = await context.Database.SqlQuery<Model>($"""
SELECT Id, AProperty, BProperty, Created FROM MyTable
""");
当我针对 SQL Server 时,一切正常,没有问题。
对于我们的单元测试,我们使用 SQLite;这就是我的问题开始的地方。
首先,SQLite 不支持
DateTimeOffset
,因此在我们的 ApplicationDbContext
中,当 DateTimeOffsetToBinaryConverter
是 Database.ProviderName
中的 Microsoft.EntityFrameworkCore.Sqlite
时,我们有一个使用 OnModelCreating
的解决方法。
此解决方法非常适合 EDM 中定义的类型,但我为此特定查询 (
Model
) 定义的类型未在 EDM 中定义,这意味着未使用该解决方法。
我尝试在
DateTimeOffset
DTO 中将数据类型从 string
切换到 Model
,这实际上对 SQLite 有效,但在 SQL Server 上失败并出现无效的强制转换异常。
我似乎也无法通过注释为特定属性指定转换器;看来只有流畅的配置才能做到这一点。
我在这里能做什么?我感觉有点卡住了..
我建议从
DateTimeOffset
切换到 string
并创建如下 DTO:
public class ModelDTO
{
public Guid Id { get; set; }
public string AProperty { get; set; }
public string BProperty { get; set; }
public string Created { get; set; }
}
然后让 EF Core 将查询结果映射到一组这样的对象。并将它们转换为
Model
s:
var models = await context.Database.SqlQuery<ModelDTO>($"""
SELECT Id, AProperty, BProperty, Created FROM MyTable
""")
.Select(m => new Model {
Id = m.Id,
AProperty = m.AProperty,
BProperty = m.BProperty,
Created = DateTimeOffset.Parse(m.Created)
});