簡體   English   中英

EF Core 7 無法反序列化 JSON 列中的動態成員

[英]EF Core 7 can't deserialize dynamic-members in JSON column

我正在嘗試將 map 我的Name列更改為動態 object。這就是原始 JSON 數據的外觀(請注意,這是從我們的舊關系數據 SQL 變形而來的,我無法通過 EF Core 生成此列或與之交互) :

{ "en": "Water", "fa": "آب", "ja": "水", ... }

請注意,可用語言存儲在單獨的表中,因此是動態定義的。

通過 T-SQL 我可以完美地與這些對象交互,例如

SELECT * 
FROM [MyObjects] 
WHERE JSON_VALUE(Name, '$.' + @languageCode) = @searchQuery

但似乎 EF Core 甚至不想將這些對象作為一個整體反序列化,更不用說查詢它們了。

我在一個簡單的GetAll查詢中得到的是一個空的Name 但其他列不受影響。

到目前為止我已經嘗試過

  1. 在內部使用帶有[JsonExtensionData]字典的空 class
  2. 使用: DynamicObject inheritance 並實施GetDynamicMembersTryGetMemberTrySetMemberTryCreateInstance
  3. 直接映射到字符串字典。
  4. 組合 1 和 2 並在頂部添加索引器運算符。

所有結果都相同:一個空的Name

我還有其他選擇,比如回到關系表,我有很多問題,硬編碼語言不是很直觀,將來可能會導致問題,使用HasJsonConversion基本上會破壞任何搜索操作的性能......所以我基本上被困在這里。

我的解決方案是我添加了一個新的 class ,它有KEYVALUE ,它將代表我需要的字典:

public class DictionaryObject
{
    public string Key { set; get; }
    public string Value { set; get; }
}

而不是在 JSON class 中包含此行:

public Dictionary<string, string> Name { get; set; }

我改為:

public List<DictionaryObject> Name { get; set; }

希望能幫助到你。

我認為目前還沒有完全支持:

  1. 您不能在表達式樹上使用動態操作,例如 Select 語句,因為它需要翻譯。
  2. JsonValue 和 JsonQuery 需要解析路徑。
  3. 如果您指定 OwnsOne(entity =>entity.owned, owned => owned.ToJson()) 並且無法解析 Json,您將收到錯誤消息。

我建議在 EF 團隊改進功能時使用此解決方法。

  1. 使用 static 方法創建 static class 以用作表達式樹中的誘餌。 這將映射到服務器內置函數。

      public static class DBF { public static string JsonValue(this string column, [NotParameterized] string path) => throw new NotSupportedException();  public static string JsonQuery(this string column, [NotParameterized] string path) => throw new NotSupportedException();  }
  2. 在 OnModelCreating 方法中包含數據庫函數。

      protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder);  modelBuilder.HasDbFunction( typeof(DBF).GetMethod(nameof(DBF.JsonValue)). ).HasName("JSON_VALUE");IsBuiltIn().  modelBuilder.HasDbFunction( typeof(DBF).GetMethod(nameof(DBF.JsonQuery)). );HasName("JSON_QUERY").IsBuiltIn().  ///... modelBuilder.Entity(entity => { //將實體視為文本 entity.Property(x => x.Metadata);HasColumnType("varchar");HasMaxLength(8000); });  }
  3. 使用 LINQ 動態調用它們。

      var a = await _context.FileInformation.AsNoTracking().Where(x => x.Metadata..JsonValue("$.Property1") == "some value").Select(x => x.Metadata..JsonValue( "$;Property2")) .ToListAsync();

您可以使用此方法添加強制轉換或什至構建匿名類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM