I have two classes that each implement an interface. One of the classes contains an ICollection of the other’s interfaces.
Now I want to map this to my database using EF but get an exception (below). Is this supposed to be possible somehow?
Entity definitions for my classes (products and categories):
public interface IProduct
{
string ProductId { get; set; }
string CategoryId { get; set; }
}
public interface ICategory
{
string CategoryId { get; set; }
ICollection<IProduct> Products { get; set; };
}
public class ProductImpl : IProduct
{
public string ProductId { get; set; }
public string CategoryId { get; set; }
}
public class CategoryImpl : ICategory
{
public string CategoryId { get; set; }
public ICollection<IProduct> Products { get; set; }
}
I want to map the relationship between CategoryImpl and ProductImpl so I’m using the following OnModelCreating method in my DbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var a = modelBuilder.Entity<CategoryImpl>();
a.ToTable("Categories");
a.HasKey(k => k.CategoryId);
a.Property(p => p.CategoryId);
a.HasMany(p => p.Products).WithOptional().HasForeignKey(p => p.CategoryId);
var b = modelBuilder.Entity<ProductImpl>();
b.ToTable("Products");
b.HasKey(k => k.ProductId);
b.Property(p => p.ProductId);
}
The exception I get is below. Am I supposed to somehow specify that the concrete type to be used for IProduct is ProductImpl?
System.InvalidOperationException: The navigation property 'Products'
is not a declared property on type 'CategoryImpl'. Verify that it has
not been explicitly excluded from the model and that it is a valid navigation property.
It’s not possible to do it with interfaces in EF. The type of a navigation property must be mapped for the property to be mapped. And for a type to be mapped it needs to be a concrete type among other things.
If you need to have different types of products and categories you could instead use a base class for them: