c# - 实体框架和 MSSQL json_value 嵌套数组在不同的行中
问题描述
我正在试验 json_value。目标是在数据库中创建动态模型,该模型可以使用 json 包含任何类型的数据。
所以这是模型:
public class DynamicModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ID { get; set; }
public string TableName { get; set; } = "MyTable";
public Guid? Container { get; set; } = null; //Parent who hold this data for many-one relation
public string Content { get; set; } = ""; //JSON content
public bool DeleteOnCascade { get; set; } = false;
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
public DateTime LastEdited { get; set; } = DateTime.UtcNow;
}
例如,如果Content
包含:
"{ \"name\":\"John\", \"age\":30, \"cars\":[] }"
如果我将汽车放在同一排,问题是数据太大,访问数据效率不高。
所以我认为如果我将汽车的嵌套列表分成不同的行会更好:
var car = new DynamicModel() {
Id = ...,
TableName = "Car",
Container = //the parent ID of the above example (one - many relation),
DeleteOnCascade = true, //Gets deleted if the parent gets deleted,
...
}
所以这里是我如何修改实体框架以便能够访问 json_value:
protected override void OnModelCreating(DbModelBuilder mb)
{
mb.Conventions.Add(new RegisterJsonValueFunctionConvention());
}
然后
public static class JH
{
// Than define your function
[DbFunction("CodeFirstDatabaseSchema", "JSON_VALUE")]
public static string JsonValue(string expression, string path)
{
throw new NotSupportedException();
}
}
然后
public class RegisterJsonValueFunctionConvention : IStoreModelConvention<EdmModel>
{
public void Apply(EdmModel item, DbModel model)
{
var expressionParameter = FunctionParameter.Create("expression", GetStorePrimitiveType(model, PrimitiveTypeKind.String), ParameterMode.In);
var pathParameter = FunctionParameter.Create("path", GetStorePrimitiveType(model, PrimitiveTypeKind.String), ParameterMode.In);
var returnValue = FunctionParameter.Create("result", GetStorePrimitiveType(model, PrimitiveTypeKind.String), ParameterMode.ReturnValue);
CreateAndAddFunction(item, "JSON_VALUE", new[] { expressionParameter, pathParameter }, new[] { returnValue });
}
protected EdmFunction CreateAndAddFunction(EdmModel item, string name, IList<FunctionParameter> parameters, IList<FunctionParameter> returnValues)
{
var payload = new EdmFunctionPayload { StoreFunctionName = name, Parameters = parameters, ReturnParameters = returnValues, Schema = GetDefaultSchema(item), IsBuiltIn = true };
var function = EdmFunction.Create(name, GetDefaultNamespace(item), item.DataSpace, payload, null);
item.AddItem(function);
return function;
}
protected EdmType GetStorePrimitiveType(DbModel model, PrimitiveTypeKind typeKind)
{
return model.ProviderManifest.GetStoreType(TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(typeKind))).EdmType;
}
protected string GetDefaultNamespace(EdmModel layerModel)
{
return layerModel.GlobalItems.OfType<EdmType>().Select(t => t.NamespaceName).Distinct().Single();
}
protected string GetDefaultSchema(EdmModel layerModel)
{
return layerModel.Container.EntitySets.Select(s => s.Schema).Distinct().SingleOrDefault();
}
}
最后,这是我访问该值的方式:
var x = db.DynamicData
.Where(m => JH.JsonValue(m.Content, "$.name").Equals("John"))
.Select(m => JH.JsonValue(m.Content, "$.age"))
.FirstOrDefault();
我想知道是否有一种方便的方法可以使用cars
Linq 查询访问?
现在我必须先获取x
值,然后查找值为 的cars
,获取列表,然后附加到确实需要时间和内存来处理它的。Container
x.ID
cars:[]
那么小伙伴们怎么看呢?有没有一种方便的方法可以以更简单的方式实现这一目标?
解决方案
您可以想象注册另一个 DB 函数以使用 JSON_QUERY() 函数,该函数可用于从 JSON 数据中选择数组和对象。
推荐阅读
- apache-kafka - Spring Cloud Stream 在没有任何字段的 Confluent Schema Registry 中生成 Avro Schema
- flutter - 必须在平面按钮的颤振中提供所需名称参数的错误
- javascript - 在 ReactJS 中显示状态变量的数据形成无限循环
- c# - ListView标签绑定不读取数据,但显示字符串的长度 - Xamarin Form
- bash - 带引号的正则表达式的 Bash 变量赋值
- testing - 编译 Rust 二进制文件,仅用于 crate 的集成测试
- java - VSCode 和 Java 设置:没有兼容的 Jar
- database - 有没有办法在模式构建器 apache 梁中配置字符串字段的长度
- json - 空手道 API 中的“call”和“callonce”有什么区别?
- python - 如何在 Python 中绘制动态图