问题
Code
I have two very simple interfaces in my application
Represents entities that are saved in the database
public interface IEntity
{
int Id { get; set; }
}
Entities that have only the Nome
field as required field to save the entity
public interface IEntityName : IEntity
{
string Nome { get; set; }
}
And many classes implementing this interface
public class Modalidade : IEntityName
{
public int Id { get; set; }
public string Nome { get; set; }
}
public class Nacionalidade : IEntityName
{
public int Id { get; set; }
public string Nome { get; set; }
}
public class Profissao : IEntityName
{
public int Id { get; set; }
public string Nome { get; set; }
}
public class TipoPessoa : IEntityName
{
public int Id { get; set; }
public string Nome { get; set; }
}
Although they the same structure, are completely different fields used for instance in this class
public class Pessoa : IEntity
{
public int Id { get; set; }
public string CPF { get; set; }
public string PIS { get; set; }
public string RG { get; set; }
public string OrgaoExpedidor { get; set; }
public string TipoDocumento { get; set; }
public DateTime? DataEmissao { get; set; }
public virtual Nacionalidade Nacionalidade { get; set; }
public virtual Profissao Profissao { get; set; }
public virtual TipoPessoa Tipo { get; set; }
....
}
Problem
Order to facilitate (and not have to create a configuration class for each new class) created a generic class configuration:
internal class EntityNameConfiguracao<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity: class, IEntityName
{
public EntityNameConfiguracao()
{
Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Nome).IsRequired().HasMaxLength(255);
}
}
This way, my setup, would
modelBuilder.Configurations.Add(new EntityNameConfiguracao<Modalidade>());
modelBuilder.Configurations.Add(new EntityNameConfiguracao<TipoPessoa>());
modelBuilder.Configurations.Add(new EntityNameConfiguracao<Nacionalidade>());
modelBuilder.Configurations.Add(new EntityNameConfiguracao<Profissao>());
Error
However, when trying to add a new migration, the following error occurs:
Command
Command in Package Manager Console: Add-Migration PessoaDadosAdicionais
Error
The property 'Id' is not a declared property on type 'Modalidade'. Verify that the property has not been explicitly excluded from the model by using the Ignore method or NotMappedAttribute data annotation. Make sure that it is a valid primitive property.
回答1:
I cannot explain why it doesn't work. It just doesn't. It doesn't work for EF 4.1 either.
This is especially surprising because it works when you convert the interfaces to abstract base classes:
public abstract class BaseEntity
{
public int Id { get; set; }
}
public abstract class BaseEntityName : BaseEntity
{
public string Nome { get; set; }
}
public class Modalidade : BaseEntityName
{
}
And then change the generic configuration to:
internal class EntityNameConfiguracao<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity: BaseEntityName
{
public EntityNameConfiguracao()
{
Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Nome).IsRequired().HasMaxLength(255);
}
}
Now, adding a concrete configuration to the model builder doesn't throw an exception:
modelBuilder.Configurations.Add(new EntityNameConfiguracao<Modalidade>());
(You must not add BaseEntity
and BaseEntityName
to the model, for example by adding DbSet
s for these classes to the context or by providing their own configuration classes, otherwise you'll get the same exception again.)
Maybe, abstract base classes are alternatives for you. Otherwise, I am afraid, you need to create concrete configuration classes for every entity to get rid of the exception.
来源:https://stackoverflow.com/questions/12762404/how-to-create-and-use-a-generic-class-entitytypeconfigurationtentity