Leo*_*ger 6 mapping entity-framework .net-core dbfunctions
我有一个具有 JObject 类型属性的实体,并且我需要能够针对这些属性使用 DbFunctions。
当我执行时,项目抛出一个异常,指出 DbFunction 不允许使用 JObject 类型的参数。
该实体就像...
public class OrchestrationRun
{
public long Id { get; set; }
public JObject MetaData { get; set; }
public JObject SystemMetaData { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
DbContext看起来像......
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions options)
: base(options)
{
}
public virtual DbSet<OrchestrationRun> OrchestrationRun { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new OrchestrationRunConfiguration());
// DbFunction mapping for JSON_VALUE
modelBuilder.HasDbFunction( typeof(MyDbContext).GetMethod(nameof(JsonValue)))
.HasName("JSON_VALUE")
.HasSchema("");
}
// DbFunction
public static string JsonValue(JObject column, [NotParameterized] string path) => throw new NotSupportedException();
}
Run Code Online (Sandbox Code Playgroud)
OrchestrationRunConfiguration是...
public class OrchestrationRunConfiguration : IEntityTypeConfiguration<OrchestrationRun>
{
public void Configure(EntityTypeBuilder<OrchestrationRun> builder)
{
builder.Property(e => e.MetaData).HasConversion(
jObject => jObject != null ? jObject.ToString(Formatting.None) : null,
json => string.IsNullOrWhiteSpace(json) ? null : JObject.Parse(json)
);
builder.Property(e => e.SystemMetaData).HasConversion(
jObject => jObject != null ? jObject.ToString(Formatting.None): null,
json => string.IsNullOrWhiteSpace(json) ? null : JObject.Parse(json)
);
}
}
Run Code Online (Sandbox Code Playgroud)
我试图执行的查询是...
var dbResponse = (from or in this.dbContext.OrchestrationRun
where MyDbContext.JsonValue(or.MetaData,"$.Product.ProductCategoryName") == "EXAMPLE"
select new
{
Id = or.Id,
CategoryId = "EXAMPLE"
}
).ToList();
Run Code Online (Sandbox Code Playgroud)
注意:异常发生在DbContext实例化时。因此,该查询永远不会被调用。
抛出的异常是...
System.InvalidOperationException:DbFunction“MyDbContext.JsonValue”的参数“column”具有无效类型“JObject”。确保当前提供程序可以映射参数类型。在 Microsoft.EntityFrameworkCore.Infrastruct.RelationalModelValidator.ValidateDbFunctions(IModel 模型) 在 Microsoft.EntityFrameworkCore.Internal.SqlServerModelValidator.Validate(IModel 模型) 在 Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ValidatingConvention.Apply(InternalModelBuilder modelBuilder)
下面的代码适用于完全相同的场景。
var jsonValueMethod = typeof(MyDbContext).GetMethod(nameof(MyDbContext.JsonValue));
builder.HasDbFunction(jsonValueMethod)
.HasTranslation(args => {
return SqlFunctionExpression.Create("JSON_VALUE", args, jsonValueMethod.ReturnType, null);
})
.HasParameter("column").Metadata.TypeMapping = new StringTypeMapping("NVARCHAR(MAX)");
Run Code Online (Sandbox Code Playgroud)
JObject下面的行具有将列转换为字符串NVARCHAR(MAX)数据类型或任何字符串数据类型的魔力。
更新:以下是 EF Core 5 及更高版本的语法。
protected override void OnModelCreating(ModelBuilder builder)
{
....
var jsonValueMethod = typeof(QueryExtentions).GetMethod(nameof(QueryExtentions.JsonValue));
var stringTypeMapping = new StringTypeMapping("NVARCHAR(MAX)");
builder
.HasDbFunction(jsonValueMethod)
.HasTranslation(args => new SqlFunctionExpression("JSON_VALUE", args, nullable: true, argumentsPropagateNullability: new[] { false, false }, jsonValueMethod.ReturnType, stringTypeMapping))
.HasParameter("column").Metadata.TypeMapping = stringTypeMapping;
.....
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3324 次 |
| 最近记录: |