Entity Framework and abstract class

4.5k views Asked by At

I'm new to Entity Framework and would like to know if, what I want to do, is possible.

I have a class named 'Monitor' which contains a List of 'MonitorField'.

Each 'MonitorField' have a List of an abstract class called 'AMonitoringTool'**

AMonitoringTool is provide to allow another developer to create his own kind of field, by inheriting from AMonitoringTool in an external DLL.

The main issue is that the application do not know the real type in 'MonitorField', preventing from saving my objects in database.

I have a MonitorEntity with a DbSet, but I can't save my Monitor list, I get this error message :

"The abstract type '{...}.AMonitoringTool' has no mapped descendant and so cannot be mapped..."

My first thought was to implement the mapping in every DLL that inherit from 'AMonitoringTool', but I don't how to do it.

MonitorEntity.cs

public class MonitorEntity : DbContext
{
    public DbSet<Monitor> Monitors { get; set; }

    public MonitorEntity()
    {

    }
}

Monitor.cs

   public class Monitor
    {
        public Monitor(string name)
        {
            MonitorName = name;
            FieldList = new List<MonitorField>();
        }

        private List<MonitorField> m_fieldList = null;
        public virtual List<MonitorField> FieldList
        {
            get
            {
                return m_fieldList;
            }
            set
            {
                m_fieldList = value;
            }
        }
    }

MonitorField.cs

public class MonitorField
{
    public AMonitoringTool Configuration { get; set; }

    public MonitorField()
    {
        FieldName = "<label>";
    }
}
1

There are 1 answers

2
DavidG On BEST ANSWER

You seem to want consumers of this library to have their own implementation of what a AMonitoringTool is. I would suggest you create your context with a generic type parameter to let the consumer decide what it is. Something like this should work:

//This isn't strictly needed but it will let you force some
//Specific fields for the monitoring tool if you like
public interface IMonitoringTool
{
    string ForcedProperty { get; set; }
}

//Here the type parameter get used for the Configuration property:
public class MonitorField<T> where T : IMonitoringTool
{
    public T Configuration { get; set; }
    public string FieldName { get; set; }

    public MonitorField()
    {
        FieldName = "<label>";
    }
}

//And this is the context:
public class MonitorEntity<T> : DbContext where T : IMonitoringTool
{
    public DbSet<Monitor<T>> Monitors { get; set; }
}

public class Monitor<T> where T : IMonitoringTool
{
    public Monitor(string name)
    {
        MonitorName = name;
        FieldList = new List<MonitorField<T>>();
    }

    public string MonitorName { get; set; }
    public List<MonitorField<T>> FieldList { get; set; }

}

So now if a consumer wants a context, they create their own class:

public MyMonitoringTool : IMonitoringTool
{
    public string ForcedProperty { get; set; }
    public string MyCustomProperty { get; set; }
}

And create their own context:

var myContext = new MonitorEntity<MyMonitoringTool>();