C# - 使用 Entity Framework Core 3 HasConversion 将字段转换为 .Net Core 3.1 中的 JSON

标签 c# json .net asp.net-core entity-framework-core

我试图在项目中的所有模型之间动态完成转换:

DbContext.cs

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    var entityTypes = modelBuilder.Model.GetEntityTypes().ToList();
    foreach (var entityType in entityTypes)
    {
        foreach (var property in entityType.ClrType.GetProperties().Where(x => x != null && x.GetCustomAttribute<HasJsonConversionAttribute>() != null))
        {
            modelBuilder.Entity(entityType.ClrType)
                .Property(property.PropertyType, property.Name)
                .HasJsonConversion();
        }
    }

    base.OnModelCreating(modelBuilder);
}

然后创建一个数据注释属性,将模型中的字段标记为“Json”

public class HasJsonConversionAttribute : Attribute {}

这是我的扩展方法,用于将 Json 转换为对象并返回 Json

public static class SqlExtensions
{
    public static PropertyBuilder HasJsonConversion(this PropertyBuilder propertyBuilder)
    {
        ParameterExpression parameter1 = Expression.Parameter(propertyBuilder.Metadata.ClrType, "v");

        MethodInfo methodInfo1 = typeof(Newtonsoft.Json.JsonConvert).GetMethod("SerializeObject", types: new Type[] { typeof(object) });
        MethodCallExpression expression1 = Expression.Call(methodInfo1 ?? throw new Exception("Method not found"), parameter1);

        ParameterExpression parameter2 = Expression.Parameter(typeof(string), "v");
        MethodInfo methodInfo2 = typeof(Newtonsoft.Json.JsonConvert).GetMethod("DeserializeObject", 1, BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder, CallingConventions.Any, types: new Type[] { typeof(string) }, null)?.MakeGenericMethod(propertyBuilder.Metadata.ClrType) ?? throw new Exception("Method not found");
        MethodCallExpression expression2 = Expression.Call(methodInfo2, parameter2);
        
        var converter = Activator.CreateInstance(typeof(ValueConverter<,>)
                                 .MakeGenericType(propertyBuilder.Metadata.ClrType, typeof(string)), new object[]
        {
            Expression.Lambda( expression1,parameter1),
            Expression.Lambda( expression2,parameter2),
            (ConverterMappingHints) null
        });

        propertyBuilder.HasConversion(converter as ValueConverter);
        return propertyBuilder;
    }
}

为了简单起见,我使用这个用户模型:

public class User : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        // Apply some settings defined in custom annotations in the model properties
        //builder.ApplyCustomAnnotationsAndConfigs(this);
    }
    
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Username { get; set; }

    [HasJsonConversion]
    public List<LocalizedName> Values { get; set; }
}

这是我想要与 JSON 相互转换的类:

public class LocalizedName
{
    public string Value { get; set; }
    public string Code { get; set; }
}

现在这是我面临的问题,它不断将 LocalizedName 对象检测为另一个没有 Keymodel 并且抛出一个错误,告诉我添加 Key/PK,即使它没有标记为模型。

现在,如果我从 User -> Configure() 执行此操作,它将起作用,但它会向我显示其他问题,例如模型失去了自己的关系以及与其他模型的关联,现在它抛出我还遇到了其他一些我一开始就没有的错误。

我还注意到 EF 从属性列表中删除了 LocalizedName 并将其显示在 Navigation 属性列表下。最后,我检查了 OnModelCreating -> modelBuilder.Model.GetEntityTypes() 并注意到 EF 将其视为新的 Model,这有点奇怪。 p>

有没有办法让 EF 将其标记为 string/json 字段,而不是 EF 自动假设它是一个模型?

如有任何帮助,我们将不胜感激。

最佳答案

所以我最终使用了 https://github.com/Innofactor/EfCoreJsonValueConverter 中的这个 NuGet 包

然后在我的DbContext.cs中:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Ignore<LocalizedName>(); //<--- Ignore this model from being added by convention
    modelBuilder.AddJsonFields(); //<--- Auto add all json fields in all models
}

然后在我的用户模型中:

public class User : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder) {}
    
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Username { get; set; }

    [JsonField] //<------ Add this attribute
    public List<LocalizedName> Values { get; set; }
}

现在它可以按预期工作。

关于C# - 使用 Entity Framework Core 3 HasConversion 将字段转换为 .Net Core 3.1 中的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65745810/

相关文章:

c# - WCF Web JSON 请求双斜线

c# - 具有内部属性的 JSON Serializer 对象

.net - 如何使用 .NET 创建 JSON 数据?

.net - 我如何通过为每个客户单独定制来有效地管理我们为多个客户提供的产品代码?

.net - 如何在 C++ 中使用 MethodInvoker?

c# - Entity Framework : Why WillCascadeOnDelete() Method is ignored?

c# - 在 C# 中使用 DateTime 的月份

c# - 如何从 url 中删除 Controller 和操作,只获取 MVC 中的 url

C# Multiline 多双引号字符串

javascript - 将嵌套且复杂的表单数据转换为 JSON