如何在经典 .NET 的 EF 6 Code First 中使用 SQL Server JSON_VALUE 函数
How can I use SQL Server JSON_VALUE function in EF 6 Code First for classic .NET
如何在经典 .NET 的 EF 6 Code First 中使用 SQL 服务器 JSON_VALUE 函数?我发现我可以在 EF Core 中这样做:
public static class JsonExtensions
{
public static string JsonValue(string column, [NotParameterized] string path)
{
throw new NotSupportedException();
}
}
// In OnModelCreating
modelBuilder.HasDbFunction(typeof(JsonExtensions).GetMethod(nameof(JsonExtensions.JsonValue)))
.HasName("JSON_VALUE")
.HasSchema("");
// And then the usage
var result = db.Blogs.Select(t => JsonExtensions.JsonValue(t.Log, "$.JsonPropertyName")).ToArray();
但是我如何在经典 .NET 的 EF 6 中实现这一点(在我的例子中,它是 4.6.1)?
在经典的 .NET 中有点不同,但仍然可以像这样:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new RegisterJsonValueFunctionConvention());
}
// Than define your function
[DbFunction("CodeFirstDatabaseSchema", "JSON_VALUE")]
public static string JsonValue(string expression, string path)
{
throw new NotSupportedException();
}
然后,因为 JSON_VALUE 未在 Entity Framework SQL 服务器提供程序清单中定义,您必须像这样创建 IStoreModelConvention:
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();
}
}
我不确定它是否适用于 Entity-Framework 6,但可能值得一提 Impatient。
它允许您对 json_value
列等执行 LINQ 查询。
如何在经典 .NET 的 EF 6 Code First 中使用 SQL 服务器 JSON_VALUE 函数?我发现我可以在 EF Core 中这样做:
public static class JsonExtensions
{
public static string JsonValue(string column, [NotParameterized] string path)
{
throw new NotSupportedException();
}
}
// In OnModelCreating
modelBuilder.HasDbFunction(typeof(JsonExtensions).GetMethod(nameof(JsonExtensions.JsonValue)))
.HasName("JSON_VALUE")
.HasSchema("");
// And then the usage
var result = db.Blogs.Select(t => JsonExtensions.JsonValue(t.Log, "$.JsonPropertyName")).ToArray();
但是我如何在经典 .NET 的 EF 6 中实现这一点(在我的例子中,它是 4.6.1)?
在经典的 .NET 中有点不同,但仍然可以像这样:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new RegisterJsonValueFunctionConvention());
}
// Than define your function
[DbFunction("CodeFirstDatabaseSchema", "JSON_VALUE")]
public static string JsonValue(string expression, string path)
{
throw new NotSupportedException();
}
然后,因为 JSON_VALUE 未在 Entity Framework SQL 服务器提供程序清单中定义,您必须像这样创建 IStoreModelConvention:
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();
}
}
我不确定它是否适用于 Entity-Framework 6,但可能值得一提 Impatient。
它允许您对 json_value
列等执行 LINQ 查询。