Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
354 views
in Technique[技术] by (71.8m points)

EF Core Value Converter does not run when DB value is null

We have a custom value converter for being able to store a JsonBlob. This works if value in the DB is a string / json string but if the value is null the Deserialize function is never hit. Is there a way to change this? This causes an issue because we would prefer to init an empty collection if there is no value.

The Converter

    public class JsonStringConvertor<T> : ValueConverter<T, string> where T : class, new()
    {
        public JsonStringConvertor(ConverterMappingHints mappingHints = null) 
            : base(convertToProviderExpression, convertFromProviderExpression, mappingHints) { }

        //Work around to dynamically create a ValueComparer<T>. Called using reflection
        public ValueComparer<T> CreateValueComparer()
        {
            var comparer = new ValueComparer<T>
            (
                (l, r) => Serialize(l) == Serialize(r),
                v => v == null ? 0 : Serialize(v).GetHashCode(),
                v => Deserialize<T>(Serialize(v))
            );
            return comparer;
        }
        
        private static readonly Expression<Func<T, string>> convertToProviderExpression = v => Serialize(v);
        private static readonly Expression<Func<string, T>> convertFromProviderExpression = v => Deserialize<T>(v) ?? new T();

        private static string Serialize<TObj>(TObj t) => JsonConvert.SerializeObject(t, EntityFrameworkJson.SerializerSettings);
        private static TVal Deserialize<TVal>(string s) => JsonConvert.DeserializeObject<TVal>(s, EntityFrameworkJson.SerializerSettings);
    }

Usage

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Model
                .GetEntityTypes()
                .SelectMany(t => t.ClrType.GetProperties()
                    .Select(p => new
                    {
                        DeclaringEntityType = t.ClrType,
                        Property = p
                    }))
                .Where(t => GetAttribute<JsonDataAttribute>(t.Property) != null)
                .ForEach(t =>
                {
                    //had to use reflection api to get all JsonData attributes, so now we reconstruct the EF PropertyBuilder 
                    var propBuilder = modelBuilder.Entity(t.DeclaringEntityType).Property(t.Property.Name);
                    
                    //Use old EF6 Naming Convention _Json 
                    var identifier = StoreObjectIdentifier.Create(propBuilder.Metadata.DeclaringEntityType, StoreObjectType.Table);
                    if (identifier != null)
                    {
                        var propName = propBuilder.Metadata.GetColumnName(identifier.Value);
                        propBuilder.Metadata.SetColumnName(propName + "_Json");
                    }
                    
                    //Setup Converter and Comparer
                    var converterType = typeof(JsonStringConvertor<>).MakeGenericType(t.Property.PropertyType);
                    var converter = (ValueConverter) Activator.CreateInstance(converterType, (object) null);

                    var comparerFunc = converter?.GetType().GetMethod("CreateValueComparer");
                    if (comparerFunc is {})
                    {
                        var comparer = (ValueComparer) comparerFunc.Invoke(converter, null);
                        propBuilder.Metadata.SetValueComparer(comparer);
                    }

                    propBuilder.HasConversion(converter);
                    propBuilder.Metadata.SetValueConverter(converter);
                    
                });

Thought it might be the comparer but it still doesn't work when not using the comparer. What i found during testing is that if the value in the database is null then the converter does not run. If i update it to an empty string it works.

we're using Entity Framework Core 5.0.1

question from:https://stackoverflow.com/questions/65625770/ef-core-value-converter-does-not-run-when-db-value-is-null

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...