ef-code-first - 如何创建和使用通用类 EntityTypeConfiguration<TEntity>

标签 ef-code-first entity-framework-5 entity-framework-migrations

代码

我的应用程序中有两个非常简单的界面

表示保存在数据库中的实体

public interface IEntity
{
    int Id { get; set; }
}

只有Nome字段作为保存实体的必填字段的实体

public interface IEntityName : IEntity
{
    string Nome { get; set; }
}   

还有很多实现这个接口(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; }
}

虽然结构一样,但是在这个类中使用的实例是完全不同的字段

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; }

    ....
}

问题

为了方便(并且不必为每个新类都创建一个配置类)创建一个泛型类配置:

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);
    }
}

这样,我的设置会

modelBuilder.Configurations.Add(new EntityNameConfiguracao<Modalidade>());
modelBuilder.Configurations.Add(new EntityNameConfiguracao<TipoPessoa>());
modelBuilder.Configurations.Add(new EntityNameConfiguracao<Nacionalidade>());
modelBuilder.Configurations.Add(new EntityNameConfiguracao<Profissao>());   

错误

但是,当尝试添加新的迁移时,出现以下错误:

命令

包管理器控制台中的命令:Add-Migration PessoaDadosAdicionais

错误

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.

最佳答案

我无法解释为什么它不起作用。它只是没有。它也不适用于 EF 4.1。

这特别令人惊讶,因为它在您将接口(interface)转换为抽象基类时起作用:

public abstract class BaseEntity
{
    public int Id { get; set; }
}

public abstract class BaseEntityName : BaseEntity
{
    public string Nome { get; set; }
}

public class Modalidade : BaseEntityName
{
}

然后将通用配置更改为:

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);
    }
}

现在,向模型构建器添加具体配置不会引发异常:

modelBuilder.Configurations.Add(new EntityNameConfiguracao<Modalidade>());

(您不得将 BaseEntityBaseEntityName 添加到模型中,例如通过将这些类的 DbSet 添加到上下文中或通过提供他们自己的配置类,否则你会再次得到同样的异常。)

也许,抽象基类是您的替代选择。否则,恐怕您需要为每个实体创建具体的配置类以摆脱异常。

关于ef-code-first - 如何创建和使用通用类 EntityTypeConfiguration<TEntity>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12762404/

相关文章:

c# - 使用 Entity Framework 更新记录 5 错误并出现 DbUpdateConcurrencyException

c# - 使用 Entity Framework Code First 版本 5 中的 SQL View

c# - EF6 中的唯一索引约定

entity-framework - Linqpad和EF5代码优先

c# - 无法在配置中设置 ProviderService

c# - "Unable to create a constant value of type [MyClass]. Only primitive types are supported in this context."

sql-server - 使用 bcp.exe 成功导入数据,即使格式文件中的列顺序与表的列顺序不同

c# - Entity Framework 迁移重命名表和列

entity-framework - 即使重置所有迁移后, Entity Framework 迁移 "context has changed"错误仍然存​​在

c# - Entity Framework 7 无法创建迁移,因为存在同名的导航属性