I have a classes which are represented as below:
public abstract class TankModel
{
protected static readonly char delimiter = ',';
protected string _destinations = "";
[Key]
public int ID { get; set; }
[NotMapped]
public String[] Destinations
{
get
{
return _destinations.Split(delimiter);
}
set
{
_destinations = String.Join($"{delimiter}", value);
}
[..........................]
}
}
public class NormalTank : TankModel
{
public double VolumeTotal { get; set; }
[.........]
}
My OnModelCreating method contains:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TankModel>().Property<string>("Outputs").HasField("_destinations");
modelBuilder.Entity<TankModel>().ToTable("Tanks");
modelBuilder.Ignore<TankModel>();
modelBuilder.Entity<NormalTank>().HasBaseType<TankModel>();
[..................]
}
When I'm displaying NormalTank rows, Destinations columns is empty.
I'm trying to display data without inheriting, then Destinations column has the right value. I suspect that modelBuilder.Ignore<TankModel>();
causes this problem, but without this property I don't build a migration.
I'm fighting with this problem since few hours and I don't see any solutions.
How can I save Destinations in my database?
Provided you are using EF Core 2.1 or greater, you can leverage a custom ValueConverter
.
E.g. for the following class:
public class Example
{
public Example() { Values = new List<string>(); }
public ICollection<string> Values { get; set; }
}
You can simply configure a converter in your DbContext
:
modelBuilder.Entity<Example>(b => b.Property(x => x.Values)
.HasConversion(new StringCollectionToStringConverter()));
Having created a converter class as follows:
public class StringCollectionToStringConverter : ValueConverter<ICollection<string>, string>
{
private static readonly Expression<Func<string, ICollection<string>>> ToListValue
= str => str.Split('|', StringSplitOptions.RemoveEmptyEntries);
private static readonly Expression<Func<ICollection<string>, string>> ToStringValue
= list => string.Join('|', list);
public StringCollectionToStringConverter(ConverterMappingHints mappingHints = null)
: base(ToStringValue, ToListValue, mappingHints) { }
public static ValueConverterInfo DefaultInfo
=> new ValueConverterInfo(typeof(ICollection<string>), typeof(string),
i => new StringCollectionToStringConverter(i.MappingHints));
}