mar*_*oss 12 c# entity-framework-core system.text.json .net-7.0 ef-core-7.0
我从 .NET 6 切换到 .NET 7,以利用 .NET 的多态序列化System.Text.Json。
在 WebApi 中,序列化和反序列化就像使用这些类型的魅力一样:
[JsonDerivedType(typeof(FileMessageData), typeDiscriminator: nameof(FileMessageData))]
public class FileMessageData : MessageData
{
public string FileName { get; set; }
}
[JsonPolymorphic]
[JsonDerivedType(typeof(FileMessageData), typeDiscriminator: nameof(FileMessageData))]
public class MessageData
{
public string InCommon { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但当谈到 EF Core 7 时,我想使用 Json Column 功能。在一个名为的实体中,我添加了一个以基本类型和此配置命名的MessageEntity属性:DataMessageData
builder.OwnsOne(e => e.Data, ownedNavigationBuilder =>
{
ownedNavigationBuilder.ToJson();
});
Run Code Online (Sandbox Code Playgroud)
现在我的期望是,当我将一个FileMessageData对象分配给Data属性时,保存的值将是
{
"$type": "FileMessageData",
"inCommon": "test",
"fileName": "hellokitty.png"
}
Run Code Online (Sandbox Code Playgroud)
但不幸的是它始终是一个空对象:
{}
Run Code Online (Sandbox Code Playgroud)
Data当我将实体上的属性类型更改为 时FileMessageData,数据库中的值为:
{
"inCommon": "test",
"fileName": "hellokitty.png"
}
Run Code Online (Sandbox Code Playgroud)
无类型鉴别器
作为解决方法,我正在这样做:
var options = new JsonSerializerOptions(JsonSerializerDefaults.General);
builder
.Property(e => e.Data)
.HasColumnType("nvarchar")
.HasMaxLength(4000)
.HasConversion(
v => JsonSerializer.Serialize(v, options),
s => JsonSerializer.Deserialize<MessageData>(s, options)!,
ValueComparer.CreateDefault(typeof(MessageData), true)
);
Run Code Online (Sandbox Code Playgroud)
...但这不允许我通过服务器评估查询“InCommon”字段,因为这显然不能转换为查询。
System.InvalidOperationException: 'The LINQ expression 'DbSet<MessageEntity>()
.Where(m => m.Data.InCommon == "HoHo")' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'
Run Code Online (Sandbox Code Playgroud)
如何告诉 EF Core 7 使用多态 JSON 功能序列化/反序列化对象?
小智 0
使用JsonProperty.EFCore可以解决您的问题。它允许您使用多态 json 字段,可编辑为IDictionary<string,object>或IList<object>作为实体模型属性。您可以将其安装为 nuget包。
使用示例:
\nusing JsonProperty.EFCore;\n\n//Create product\nvar product = new Product() { Name = "Car" };\n\n//AddRange\nproduct.Attributes.AddRange(new Dictionary<string, object>() {\n //You can add values \xe2\x80\x8b\xe2\x80\x8bof different types if the base type is object \n {"MaxSpeed",300},{ "Engine capacity",3.5}, { "ElectroCar",false }\n});\n\n//Add\nproduct.Attributes.Add("Color", "Red");\n\n//Edit\nproduct.Attributes.Edit(attrs=>{\n attrs["Color"] = "Blue";\n return attrs;\n});\n\n//Entity model\npublic class Product\n{\n public int Id { get; set; }\n public string Name { get; set; }\n //Json container property. Same type as JsonDictionary<string,object>\n public JsonDictionary Attributes{ get; set; } = new();\n}\nRun Code Online (Sandbox Code Playgroud)\n