How to store JSON in an entity field with EF Core?

前端 未结 10 505
死守一世寂寞
死守一世寂寞 2020-11-29 17:13

I am creating a reusable library using .NET Core (targeting .NETStandard 1.4) and I am using Entity Framework Core (and new to both). I have an entity class that looks like

10条回答
  •  无人及你
    2020-11-29 18:03

    // DbContext

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

    Create an attribute to handle the properties of the entities.

    
    public class HasJsonConversionAttribute : System.Attribute
        {
    
        }
    

    Create extention class to find Josn properties

        public static class ValueConversionExtensions
        {
            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(typeof(List), typeof(string)), new object[]
                    {
                        Expression.Lambda( expression1,parameter1),
                        Expression.Lambda( expression2,parameter2),
                        (ConverterMappingHints) null
                    });
    
                propertyBuilder.HasConversion(converter as ValueConverter);
    
                return propertyBuilder;
            }
        }
    

    Entity example

     public class Attribute
        {
            [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
            public int Id { get; set; }
            public string Name { get; set; }
    
            [HasJsonConversion]
            public List Values { get; set; }
        }
    
        public class AttributeValue
        {
            public string Value { get; set; }
            public IList Translations { get; set; }
        }
    
        public class AttributeValueTranslation
        {
            public string Translation { get; set; }
    
            public string CultureName { get; set; }
        }
    

    Download Source

提交回复
热议问题