"The following scenario in which the entity set is of the base type works as expected:
using System.Data.Entity;
namespace ConsoleApplication13
{
class Program
{
static void Main(string[] args)
{
using (var context = new MyContext())
{
context.Customers.Add(new Customer() { Name = ""a"" });
context.SaveChanges();
}
}
}
public class BaseEntity
{
public int Id { get; private set; }
}
public class Customer : BaseEntity
{
public string Name { get; set; }
}
public class MyContext : DbContext
{
//public DbSet<Customer> Customers { get; set; }
public DbSet<BaseEntity> Customers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//modelBuilder.Entity<Customer>().HasKey(e => e.Id);
}
}
}
Changing the code to make the entity set of the derived type as follows:
using System.Data.Entity;
namespace ConsoleApplication13
{
class Program
{
static void Main(string[] args)
{
using (var context = new MyContext())
{
context.Customers.Add(new Customer() { Name = ""a"" });
context.SaveChanges();
}
}
}
public class BaseEntity
{
public int Id { get; private set; }
}
public class Customer : BaseEntity
{
public string Name { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
//public DbSet<BaseEntity> Customers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//modelBuilder.Entity<Customer>().HasKey(e => e.Id);
}
}
}
Causes the following exception to be thrown in the line containg the call to the Add method (notice the non-text characters used in the exception message):
System.Data.Entity.ModelConfiguration.ModelValidationException was unhandled
Message=One or more validation errors were detected during model generation:
System.Data.Edm.EdmEntityType: : EntityType 'Customer' has no key defined. Define the key for this EntityType.
System.Data.Edm.EdmEntitySet: EntityType: EntitySet �Customers� is based on type �Customer� that has no keys defined.
Source=EntityFramework
StackTrace:
at System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl(EdmModel model, XmlWriter writer)
at System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl(EdmModel model)
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
at ConsoleApplication13.Program.Main(String[] args) in C:\Users\divega\Documents\Visual Studio 2010\Projects\ConsoleApplication13\ConsoleApplication13\Program.cs:line 11
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Finally, uncommenting the line containing the call to HasKey in the OnModelCreating method as follows:
using System.Data.Entity;
namespace ConsoleApplication13
{
class Program
{
static void Main(string[] args)
{
using (var context = new MyContext())
{
context.Customers.Add(new Customer() { Name = ""a"" });
context.SaveChanges();
}
}
}
public class BaseEntity
{
public int Id { get; private set; }
}
public class Customer : BaseEntity
{
public string Name { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
//public DbSet<BaseEntity> Customers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>().HasKey(e => e.Id);
}
}
}
Causes the following exception in the line containing the call to the Add method:
System.InvalidOperationException was unhandled
Message=The key component 'Id' is not a declared property on type 'Customer'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.
Source=EntityFramework
StackTrace:
at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureKey(EdmEntityType entityType)
at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EdmEntityType entityType, EdmModel model)
at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel model)
at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(EdmModel model)
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
at ConsoleApplication13.Program.Main(String[] args) in C:\Users\divega\Documents\Visual Studio 2010\Projects\ConsoleApplication13\ConsoleApplication13\Program.cs:line 11
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
I have investigated the issue and found that this is because we require properties to have a setter (even private), but if the property is obtained from an inheriting type, not the declaring type, and there is only a private setter on the declaring type we fail to recognize that. This assumption is scattered in many places: code first, ObjectItemConventionAssemblyLoader, materialization (translator). While I have prototyped a fix that passes “dp run”, the change seems risky to me for RC. My main worry is that there may be many other places were this assumption is made that we may not be seeing/catching. In addition is would be a breaking change, as we would be mapping properties that we did not map/”see” before: i.e. properties with these characteristics.
(There is a prototype of this bug fix already. Details are included in the internal bug entry)
"
This item was migrated from the DevDiv work item tracking system [ID=323531].