I'm using Entity Framework (version 6.1.1) code first and the WCF Data Services EntityFramework Provider (still in 1.0.0-beta2 prerelease) to provide the services.
This setup works fine for applications where there are no EF classes that inherit from others.
However, I have an application where I am implementing table per type (TPT) inheritance. Consider the following code first classes:
public class Customer
{
public Guid CustomerID { get; set; }
public string CustomerName { get; set; }
}
public class Organization : Customer
{
public string OrganizationName { get; set; }
}
These are mapped in a table per type fashion as:
public class CustomerMap : EntityTypeConfiguration<Customer>
{
public CustomerMap()
{
this.HasKey(t => t.CustomerID);
this.Property(t => t.CustomerID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(t => t.CustomerName)
.IsRequired()
.HasMaxLength(255);
this.ToTable("tblCustomers_Customer");
this.Property(t => t.CustomerID).HasColumnName("CustomerID");
this.Property(t => t.CustomerName).HasColumnName("CustomerName");
}
}
public class OrganizationMap : EntityTypeConfiguration<Organization>
{
public OrganizationMap()
{
this.HasKey(t => t.CustomerID);
this.Property(t => t.CustomerID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(t => t.OrganizationName)
.IsRequired()
.HasMaxLength(255);
this.ToTable("tblCustomers_Organization");
this.Property(t => t.CustomerID).HasColumnName("CustomerID");
}
}
And the context class:
public class ModelContext: DbContext
{
static ModelContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ModelContext, Migrations.Configuration>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CustomerMap());
modelBuilder.Configurations.Add(new OrganizationMap());
}
public DbSet<Customer> Customers { get; set; }
public DbSet<Organization> Organizations { get; set; }
}
And the WCF data service using the Entity Framework Provider:
public class EFDS : EntityFrameworkDataService<ModelContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Customers", EntitySetRights.All);
config.SetEntitySetAccessRule("Organizations", EntitySetRights.All);
}
}
When the service is initializing, I get the following error, in which the entity set is not found, even though it is defined in the context class:
The given name 'Organizations' was not found in the entity sets.
Parameter name: name
Any ideas?
This is by design as per this msdn forum post:
This is a by designed feature that the refection provider(WCF Data Service provider) is designed to walk all public types/properties, the reflection provider can only expose one entity set for each type hierarchy. It doesn't support so called "MEST" (Multiple Entity Sets per Type), because it would not know which one to pick.
So, my updated WCF service needs to include only the base types, and make sure version 3 of the data service protocol is being used in order to use OfType<>
, etc. to be able to query and update extending entities:
public class EFDS : EntityFrameworkDataService<ModelContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
config.SetEntitySetAccessRule("Customers", EntitySetRights.All);
}
}