2

Let's say I have two different classes. They share some properties, but also have some individual ones.

public class A
{
    // Shared properties
    public int Id { get; set; }
    public DateTime CreatedDtm { get; set; }
    public string CreatedBy { get; set; }

    // Individual properties
    public string PhoneNumber { get; set; }
    public string EmailAddress { get; set; }
}

public class B
{
    // Shared properties
    public int Id { get; set; }
    public DateTime CreatedDtm { get; set; }
    public string CreatedBy { get; set; }

    // Individual properties
    public string StreetAddress { get; set; }
    public string PostalCode{ get; set; }
    public string City{ get; set; }
}

Now the trick is, that I would like to store these two types as the same entity. This is possible, if I convert the individual properties to JSON. So I could make a shared entity, like this:

public class C
{
    // Shared properties
    public int Id { get; set; }
    public DateTime CreatedDtm { get; set; }
    public string CreatedBy { get; set; }

    // Individual properties
    public object IndividualProperties { get; set; }
}

But if I do this, I lose all the advantages of a static typed language as well as all the benefits of polymorphism, doing this (e.g. class A might have some different validations from class B).

Isn't there some way of doing the conversion, just before saving the entity, via Entity Framework (Core)? I could of course write the mapping myself, but I got a feeling that there should be a shortcut to this...

Basically, I want to do something like this (doesn't matter if it's an interface, abstract class or something completely different):

public void AddEntity(ISomeSharedInterface entity) 
{
    C sharedEntity = SomeMappingMethod(entity);
    db = new Context();
    db.SharedEntities.Add(sharedEntity);
    db.SaveChanges();
}

If you wonder about this design, it is for an automation process. The various sub-forms which needs to be filled during the process vary, but I would like to store all items in the same table.

Jakob Busk Sørensen
  • 5,599
  • 7
  • 44
  • 96

1 Answers1

2

If you create an abstract base class, this should just work without any additional configuration:

public abstract class Base
{
    // Shared properties
    public int Id { get; set; }
    public DateTime CreatedDtm { get; set; }
    public string CreatedBy { get; set; }
}

public class A : Base
{
    // Individual properties
    public string PhoneNumber { get; set; }
    public string EmailAddress { get; set; }
}

public class B : Base
{
    // Individual properties
    public string StreetAddress { get; set; }
    public string PostalCode{ get; set; }
    public string City{ get; set; }
}

class Context : DbContext
{
    DbSet<Base> Bases { get; set; }
}

public void AddEntity(Base entity) 
{
    using (db = new Context())
    {
        db.Bases.Add(entity);
        db.SaveChanges();
    }
}

More info here.

Johnathan Barclay
  • 18,599
  • 1
  • 22
  • 35
  • So that means that I would not get a JSON blob in my database, but instead a column for each property and then `null` if there is not value for the property, for that specific class, right? – Jakob Busk Sørensen Jan 07 '20 at 13:04
  • @Noceo that's correct. It will also add a "shadow" discriminator column to identify the entity type of each row. – Johnathan Barclay Jan 07 '20 at 13:05
  • That's an interesting approach. Although I like the end result better, with a JSON blob, I do like the part of this, which is working with EF Core, rather than against it (as it seems I am doing). I will let you know, how it works out. – Jakob Busk Sørensen Jan 07 '20 at 13:07