C#-在.Net Core 3.1中使用Entity Framework Core 3 HasConversion将字段转换为JSON [英] C# - Using Entity Framework Core 3 HasConversion to convert a field to JSON in .Net Core 3.1

查看:123
本文介绍了C#-在.Net Core 3.1中使用Entity Framework Core 3 HasConversion将字段转换为JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was trying to accomplish the conversion dynamically across all of the models I have in my project:

DbContext.cs

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"

Then created a data annotation attribute to mark my fields in my model as "Json"

public class HasJsonConversionAttribute : Attribute {}

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

This is my extension method used to convert the Json to object and back to 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;
    }
}

为简单起见,我使用此用户模型:

For simplicity I'm using this User model:

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相互转换的类:

and This is the class that I want to convert to and from JSON:

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

现在这是我面临的问题,它继续将 LocalizedName 对象检测为另一个没有 Key model 抛出一个错误,告诉我添加 Key/PK ,即使未将其标记为模型.

Now here's the problem I'm facing, it keeps on detecting LocalizedName object as another model that doesn't have a Key and throws an error telling me to add a Key/PK even though this is not flagged as a model.

现在,如果我从 User->执行此操作,Configure()它将起作用,但会向我显示其他问题,例如该模型失去与其他模型的关系和关联,而现在却抛出了我本来没有的其他错误集

Now if I execute this from the User -> Configure() it will work BUT it'll show me other issues like the model loses its own relationships and associations with other models and now it throws me other set of errors which I didn't even have in the first place.

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

I've also noticed that EF removes LocalizedName from the property list and shows it under Navigation properties list. And lastly, I've checked the OnModelCreating -> modelBuilder.Model.GetEntityTypes() and noticed that EF is treating it as a new Model which is kinda weird.

有没有一种方法可以告诉 EF 将其标记为 string/json 字段,而不是EF自动假定它是模型?

Is there a way I can tell EF to mark this as a string/json field instead of EF auto-assuming it's a model?

任何帮助将不胜感激.

推荐答案

所以我最终使用了NuGet包rel ="nofollow noreferrer"> https://github.com/Innofactor/EfCoreJsonValueConverter

So I ended up using this NuGet package from https://github.com/Innofactor/EfCoreJsonValueConverter

然后在我的 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; }
}

现在它可以正常工作了.

Now it works as expected.

这篇关于C#-在.Net Core 3.1中使用Entity Framework Core 3 HasConversion将字段转换为JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆