how to Store/Map Complex data type using EF?

51 Views Asked by At

CategoryModel has a property & dependency-property Color of type Object Brush (Complex data type) that can't be Stored using EF directly so I use Serialization and store it as string.

using System.ComponentModel.DataAnnotations.Schema;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public class CategoryModel : UserControl{
...
    [NotMapped] // Not mapped to the database
    public Brush Color
    {
        get { return (Brush)GetValue(ColorProperty); }
        set { SetValue(ColorProperty, value); }
    }

    public static readonly DependencyProperty ColorProperty =
    DependencyProperty.Register("Color", typeof(Brush), typeof(CategoryModel), new PropertyMetadata(Brushes.Black));
...
}

so the solution is to use get & set to & from another property let's call it serializedBrush of type string.

the Problem is: the property is already using get & set to & from the dependency-property.

suggested this approach to ChatGPT: So I changed the dependency-property to serializedBrush string

public class CategoryModel : UserControl{
    ...
    public Brush Color
    {
        get { return JsonSerializer.Deserialize<Brush>(SerializedBrush); }
        set { SerializedBrush = JsonSerializer.Serialize(value); }
    }

    public static readonly DependencyProperty SerializedBrush=
    DependencyProperty.Register("Color", typeof(string), typeof(CategoryModel));
}

AI comment: don't use dependency property to interact with the database, it is used more to deal with the business logic, and gave me the following solution

using System.ComponentModel.DataAnnotations.Schema;
using System.Windows;
using System.Windows.Media;
using System.Text.Json;

namespace YourNamespace
{
    public class CategoryModel : DependencyObject
    {
        
        public static readonly DependencyProperty SerializedBrushProperty =
            DependencyProperty.Register("SerializedBrush", typeof(string), typeof(CategoryModel));
        [Column(TypeName = "nvarchar(max)")] // Specify column type for EF
        public string SerializedBrush
        {
            get { return (string)GetValue(SerializedBrushProperty); }
            set { SetValue(SerializedBrushProperty, value); }
        }

        public Brush Color
        {
            get { return JsonSerializer.Deserialize<Brush>(SerializedBrush); }
            set { SerializedBrush = JsonSerializer.Serialize(value); }
        }
    }
}

but what about the dependency property of the Brush Color

1

There are 1 best solutions below

1
Shadow On BEST ANSWER

adding another property to be used for serialization or change the color to RGB
for
a property that has < dependency-property > related to it, is the cause/source of the problem.
because you will then have 3 properties that you need to somehow identify the relation (getters & setters) between them.

Solution : we got 2 options:

First: use Value Conversion in the "OnModelCreating()" method in the DbContext.

you can do that in the model class (CategoryModel)

using System.ComponentModel.DataAnnotations.Schema;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public class CategoryModel : UserControl{
...
    [Column(TypeName = "nvarchar(24)")] // EF8 will automatically pick the pre-configured conversion method for it.
    public Brush Color
    {
        get { return (Brush)GetValue(ColorProperty); }
        set { SetValue(ColorProperty, value); }
    }

    public static readonly DependencyProperty ColorProperty =
    DependencyProperty.Register("Color", typeof(Brush), typeof(CategoryModel), new PropertyMetadata(Brushes.Black));
...
}

Or in the DbContext OnModelCreating() method

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<CategoryModel>()
        .Property(e => e.Color)
        .HasConversion<string>();
}

Second: leverage Entity Framwork Core 8's ability to store complex types as JSON. (might provide the solution for it later)

Thank you everyone, and special thanks to Jeremy Lakeman.