C# 禁用EF Core';s包括所有财产的惯例

C# 禁用EF Core';s包括所有财产的惯例,c#,entity-framework,entity-framework-core,C#,Entity Framework,Entity Framework Core,EF Core(与之前的EF一样)会自动添加到模型中 我使用Fluent API,我需要记住忽略它们,这会变得很乏味——我总是会遇到运行时错误,因为我总是忘记 我希望EF只包括我配置的那些属性 如何禁用此约定?在ConventionSet对象中调用DbContext.OnModelCreating之前,EF Core将收集将应用的约定,传递给OnModelCreating的ModelBuilber将已经包含由约定发现的实体和属性 然而,约定并不只是代表“一开始就做一次,然后忘记它们”规则来确定模

EF Core(与之前的EF一样)会自动添加到模型中

我使用Fluent API,我需要记住忽略它们,这会变得很乏味——我总是会遇到运行时错误,因为我总是忘记

我希望EF只包括我配置的那些属性


如何禁用此约定?

在ConventionSet对象中调用DbContext.OnModelCreating之前,EF Core将收集将应用的约定,传递给OnModelCreating的ModelBuilber将已经包含由约定发现的实体和属性

然而,约定并不只是代表“一开始就做一次,然后忘记它们”规则来确定模型,每当您使用Fluent API更改模型时,它们都会不断应用。如果手动添加实体,则此时将执行用于发现属性等的约定,并且模型始终保持最新

ConventionSet对象定义了一个“事件”列表,如“添加的实体类型”,并为每个事件定义了要执行的约定

其中一个事件是“ModelInitialized”,它在一开始就运行,通过DbSetFindingConvention最初标识实体。但是,此约定找到的每个实体类型都将触发“事件”EntyTypeAddedConventions,该EntyTypeAddedConventions随后将标识实体上的属性等。如果只是取消DbSetFindingConvention,则在手动向模型添加实体类型后,仍然会自动获取属性

为了抑制属性生成,还需要从EntyTypeAddedConventions中删除PropertyDiscoveryConvention

删除所有约定可能不是一个好主意,因为您需要手动执行所有操作,这是一项乏味的工作。但是,如果你很好地理解了你想使用的自动功能,以及哪种约定做了什么,你可以有选择地删除其中的一些

要取消约定,您可以交换–特定于数据库提供程序!!!–ConventionSetBuilder服务实现

public class CustomSqlServerConventionSetBuilder : SqlServerConventionSetBuilder {

    //See also notes in CustomRuntimeConventionSetBuilder


    public CustomSqlServerConventionSetBuilder([NotNullAttribute] ProviderConventionSetBuilderDependencies dependencies, [NotNullAttribute] RelationalConventionSetBuilderDependencies relationalDependencies, [NotNullAttribute] ISqlGenerationHelper sqlGenerationHelper)
    : base(dependencies, relationalDependencies, sqlGenerationHelper) {
    }

    public override ConventionSet CreateConventionSet() {
        ConventionSet cs =  base.CreateConventionSet();
        //Do not find entity types automatically
        DbSetFindingConvention dbSetFindingConvention = cs.ModelInitializedConventions.OfType<DbSetFindingConvention>().FirstOrDefault();
        if (dbSetFindingConvention != null) {
            cs.ModelInitializedConventions.Remove(dbSetFindingConvention);
        }
        //Do not find properties automatically
        PropertyDiscoveryConvention propertyDiscoveryConvention = cs.EntityTypeAddedConventions.OfType<PropertyDiscoveryConvention>().FirstOrDefault();
        if (propertyDiscoveryConvention != null) {
            cs.EntityTypeAddedConventions.Remove(propertyDiscoveryConvention);
        }
        propertyDiscoveryConvention = cs.EntityTypeBaseTypeChangedConventions.OfType<PropertyDiscoveryConvention>().FirstOrDefault();
        if (propertyDiscoveryConvention != null) {
            cs.EntityTypeBaseTypeChangedConventions.Remove(propertyDiscoveryConvention);
        }

        return cs;
    }

}
公共类CustomSqlServerConventionSetBuilder:SqlServerConventionSetBuilder{
//另请参见CustomRuntimeConventionSetBuilder中的注释
公共自定义SQLServerConventionSetBuilder([NotNullAttribute]ProviderConventionSetBuilderDependencies依赖项,[NotNullAttribute]关系约定SetBuilderDependencies关系依赖项,[NotNullAttribute]ISqlGenerationHelper sqlGenerationHelper)
:base(依赖项、关系依赖项、sqlGenerationHelper){
}
公共覆盖约定集CreateConventionSet(){
ConventionSet cs=base.CreateConventionSet();
//不自动查找实体类型
DbSetFindingConvention DbSetFindingConvention=cs.ModelInitializedConventions.OfType().FirstOrDefault();
if(dbSetFindingConvention!=null){
cs.ModelInitializedConventions.Remove(dbSetFindingConvention);
}
//不自动查找属性
PropertyDiscoveryConvention PropertyDiscoveryConvention=cs.EntityTypeAddedConventions.OfType().FirstOrDefault();
if(propertyDiscoveryConvention!=null){
cs.EntityTypeAddedConventions.Remove(propertyDiscoveryConvention);
}
propertyDiscoveryConvention=cs.EntityTypeBaseTypeChangedConventions.OfType().FirstOrDefault();
if(propertyDiscoveryConvention!=null){
cs.EntityTypeBaseTypeChangedConventions.Remove(propertyDiscoveryConvention);
}
返回cs;
}
}
替换DbContext类中DI服务的默认实现(例如):

protectedoverride void onconfig(DbContextOptionsBuilder optionsBuilder){
optionsBuilder.ReplaceService();
}
或者,如果希望避免使此覆盖数据库提供程序特定,也可以将RuntimeConventionSetBuilder子类化,覆盖CreateConventionSet方法,并将其注册到服务IConventionSetBuilder。但这种接口在未来更有可能发生变化

公约的执行情况可在以下网址找到: 文档可在此处找到:

您应该检查特定约定实现了哪些“事件”,如果该约定应被抑制,则通常应从每个“事件”中删除该约定


这对EF Core 5.0有效,在以前的版本中可能有所不同。您还可以看看什么是“运行时错误”?@LeiYang该属性是/未配置的,我使用/不使用它,但不知道EF对它的看法不同。然而,这不是真正的问题-即使我没有收到错误,我仍然希望禁用此约定。@LeiYang我希望删除实际问题,即约定。如果可能的话,就是这样。我找不到办法,但EF Core中有很多东西还没有被记录下来,所以也许有办法,但我不知道。@LeiYang我知道,那又怎样?@LeiYang我想依靠官方的方法,而不是挖掘源代码。有些东西没有记录在官方网站上,而是在EF作者的各种博客上。我想知道什么是可能的。
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {  
 optionsBuilder.ReplaceService<Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure.IProviderConventionSetBuilder, TechnicalUtilities.CustomSqlServerConventionSetBuilder>();
    
    }