惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
A
Arctic Wolf
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Schneier on Security
T
Tenable Blog
I
Intezer
S
Securelist
Scott Helme
Scott Helme
V
Visual Studio Blog
Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
T
The Blog of Author Tim Ferriss
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AWS News Blog
AWS News Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
L
LangChain Blog
F
Fortinet All Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cisco Blogs
L
Lohrmann on Cybersecurity
M
MIT News - Artificial intelligence
G
GRAHAM CLULEY
博客园 - 司徒正美
aimingoo的专栏
aimingoo的专栏
雷峰网
雷峰网
MyScale Blog
MyScale Blog
D
DataBreaches.Net
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
C
CXSECURITY Database RSS Feed - CXSecurity.com
量子位
博客园 - 三生石上(FineUI控件)
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
云风的 BLOG
云风的 BLOG
大猫的无限游戏
大猫的无限游戏
GbyAI
GbyAI
Cisco Talos Blog
Cisco Talos Blog
Security Latest
Security Latest
Project Zero
Project Zero
K
Kaspersky official blog
罗磊的独立博客
Know Your Adversary
Know Your Adversary
T
The Exploit Database - CXSecurity.com
P
Privacy International News Feed
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Apple Machine Learning Research
Apple Machine Learning Research

博客园 - 东邪独孤

【ASP.NET Core】在 Windows Forms 中运行 Web 服务器 【EF Core】级联删除行为 【EF Core】继承策略——TPC 【EF Core】继承策略——TPT 【EF Core】继承策略——TPH 【EF Core】使用自定义的值比较器 【EF Core】值转换器 【EF Core】直接更新数据 【EF Core】实体追踪——Entry中记录的数据 【EF Core】实体状态与变更追踪 【EF Core】将一个实体映射到多个表的正确方法 【EF Core】“Code First”方案下以编程方式生成迁移 【EF Core】“DB First”方案下用编程方式生成数据库模型代码 【EF Core】三种方法记录生成的 SQL 语句 【EF Core】未定义实体类的数据库模型 【EF Core】“多对多”关系与跳跃导航 【EF Core】FromExpression 方法有什么用? 【EF Core】通过 DbContext 选项扩展框架 【EF Core】框架底层的数据库连接管理 【EF Core】再谈普通实体关系与 Owned 关系的区别 【EF Core】优化后的模型 【EF Core】使用外部 Model 【EF Core】聊聊“复合”属性 【EF Core】为 DatabaseFacade 扩展“创建”与“删除”数据表功能 【EF Core】带主键实体与无主键实体 【EF Core】框架是如何识别实体类的属性和主键的
【EF Core】实体类的依赖注入
东邪独孤 · 2025-09-06 · via 博客园 - 东邪独孤

在使用外部模型那篇水文中,有大伙伴提出:老周,你那个 Ultraman 类和 Speciality 类的的关系是不是有问题,外键不应该在 Speciality 类上吗,怎么会跑到 Ultraman 类上?因为它们是一对一关系,在配置的时候你也可以反过来,主要区别是谁引用谁的问题,由于是一对一引用,所以反过来也可以的。

今天咱们聊聊实体类构造函数的依赖注入。实体类也支持依赖注入,不过,目前版本只支持注入 EF Core 自己的服务类型,你在代码中添加的应用程序级服务类型不能注入(以后可能会支持)。总结一下,以下服务类型可以注入:

1、EF Core 框架内部注册的服务类型;

2、三个补充类型:

  a、当前 DbContext 实例(你从 DbContext 派生的类);

  b、当前实体相关的 IEntityType,可以获取实体模型相关信息;

  c、ILazyLoader 接口,延时加载时用得上。

现在要解决一个问题:我怎么知道 EF Core 框架内部哪些服务可以注入?这个活儿有两个方案:第一个方案是看 EF Core 源代码,在 EFCore\Infrastructure 下,注意看 EntityFrameworkServicesBuilder 类的 CoreServices 字段或 TryAddCoreServices 方法,基本齐全了。

    public static readonly IDictionary<Type, ServiceCharacteristics> CoreServices
        = new Dictionary<Type, ServiceCharacteristics>
        {
            { typeof(LoggingDefinitions), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IDatabaseProvider), new ServiceCharacteristics(ServiceLifetime.Singleton, multipleRegistrations: true) },
            { typeof(IDbSetFinder), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IDbSetInitializer), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IDbSetSource), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IEntityFinderSource), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IStructuralTypeMaterializerSource), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(ITypeMappingSource), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IModelCustomizer), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IModelCacheKeyFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IModelSource), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IModelRuntimeInitializer), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IInternalEntrySubscriber), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IEntityEntryGraphIterator), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IValueGeneratorCache), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(ISingletonOptionsInitializer), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(ILoggingOptions), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(ICoreSingletonOptions), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IModelValidator), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(ICompiledQueryCache), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IValueConverterSelector), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IConstructorBindingFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IRegisteredServices), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IPropertyParameterBindingFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IParameterBindingFactories), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IMemberClassifier), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IMemoryCache), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IEvaluatableExpressionFilter), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(INavigationExpansionExtensibilityHelper), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(ILiftableConstantFactory), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IExceptionDetector), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IJsonValueReaderWriterSource), new ServiceCharacteristics(ServiceLifetime.Singleton) },
            { typeof(IProviderConventionSetBuilder), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IConventionSetBuilder), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDiagnosticsLogger<>), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IInterceptors), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(ILoggerFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IEntityGraphAttacher), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IKeyPropagator), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(INavigationFixer), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(ILocalViewListener), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IStateManager), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IConcurrencyDetector), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IInternalEntityEntryNotifier), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IValueGenerationManager), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IChangeTrackerFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IChangeDetector), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDbContextServices), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IValueGeneratorSelector), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IExecutionStrategyFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IExecutionStrategy), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IAsyncQueryProvider), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IQueryCompiler), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(ICompiledQueryCacheKeyGenerator), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IModel), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDesignTimeModel), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IUpdateAdapterFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(ICurrentDbContext), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDbContextDependencies), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDatabaseFacadeDependencies), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDbContextOptions), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDatabase), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDatabaseCreator), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDbContextTransactionManager), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IQueryContextFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IQueryCompilationContextFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IQueryableMethodTranslatingExpressionVisitorFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IQueryTranslationPreprocessorFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IQueryTranslationPostprocessorFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IShapedQueryCompilingExpressionVisitorFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IDbContextLogger), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IAdHocMapper), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(ILiftableConstantProcessor), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(ILazyLoader), new ServiceCharacteristics(ServiceLifetime.Transient) },
            { typeof(ILazyLoaderFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) },
            { typeof(IParameterBindingFactory), new ServiceCharacteristics(ServiceLifetime.Singleton, multipleRegistrations: true) },
            { typeof(ITypeMappingSourcePlugin), new ServiceCharacteristics(ServiceLifetime.Singleton, multipleRegistrations: true) },
            {
                typeof(IEvaluatableExpressionFilterPlugin),
                new ServiceCharacteristics(ServiceLifetime.Singleton, multipleRegistrations: true)
            },
            { typeof(ISingletonOptions), new ServiceCharacteristics(ServiceLifetime.Singleton, multipleRegistrations: true) },
            { typeof(IConventionSetPlugin), new ServiceCharacteristics(ServiceLifetime.Scoped, multipleRegistrations: true) },
            { typeof(ISingletonInterceptor), new ServiceCharacteristics(ServiceLifetime.Singleton, multipleRegistrations: true) },
            { typeof(IResettableService), new ServiceCharacteristics(ServiceLifetime.Scoped, multipleRegistrations: true) },
            { typeof(IInterceptor), new ServiceCharacteristics(ServiceLifetime.Scoped, multipleRegistrations: true) },
            { typeof(IInterceptorAggregator), new ServiceCharacteristics(ServiceLifetime.Scoped, multipleRegistrations: true) }
        };

这个字典的 Key 就是核心服务的类型。Relational 库和数据库提供者可能会补充一些服务,但大都多是替换服务,即接口类型是不变的。

第二个方案是通过一个叫 IRegisteredServices 的服务,它可以列出已注册服务的 Type 列表。

using (var c = new DemoContext())
{
    IRegisteredServices regsvcs = c.GetService<IRegisteredServices>
();
    foreach (var sv in regsvcs.Services)
    {
        Console.WriteLine(sv);
    }
    ……
}

这样就会列出内部已注册服务的类型。

Microsoft.EntityFrameworkCore.Diagnostics.LoggingDefinitions
Microsoft.EntityFrameworkCore.Storage.IDatabaseProvider
Microsoft.EntityFrameworkCore.ValueGeneration.IValueGeneratorCache
Microsoft.EntityFrameworkCore.Storage.IRelationalTypeMappingSource
Microsoft.EntityFrameworkCore.Storage.ISqlGenerationHelper
Microsoft.EntityFrameworkCore.Metadata.IRelationalAnnotationProvider
Microsoft.EntityFrameworkCore.Migrations.IMigrationsAnnotationProvider
Microsoft.EntityFrameworkCore.Infrastructure.IModelValidator
Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure.IProviderConventionSetBuilder
Microsoft.EntityFrameworkCore.Update.IUpdateSqlGenerator
Microsoft.EntityFrameworkCore.Query.IEvaluatableExpressionFilter
Microsoft.EntityFrameworkCore.Storage.IRelationalTransactionFactory
Microsoft.EntityFrameworkCore.Update.IModificationCommandBatchFactory
Microsoft.EntityFrameworkCore.Update.IModificationCommandFactory
Microsoft.EntityFrameworkCore.ValueGeneration.IValueGeneratorSelector
Microsoft.EntityFrameworkCore.Storage.IRelationalConnection
Microsoft.EntityFrameworkCore.Migrations.IMigrationsSqlGenerator
Microsoft.EntityFrameworkCore.Storage.IRelationalDatabaseCreator
Microsoft.EntityFrameworkCore.Migrations.IHistoryRepository
Microsoft.EntityFrameworkCore.Storage.IExecutionStrategyFactory
Microsoft.EntityFrameworkCore.Query.IRelationalQueryStringFactory
Microsoft.EntityFrameworkCore.Query.ICompiledQueryCacheKeyGenerator
Microsoft.EntityFrameworkCore.Query.IQueryCompilationContextFactory
Microsoft.EntityFrameworkCore.Query.IMethodCallTranslatorProvider
Microsoft.EntityFrameworkCore.Query.IAggregateMethodCallTranslatorProvider
Microsoft.EntityFrameworkCore.Query.IMemberTranslatorProvider
Microsoft.EntityFrameworkCore.Query.IQuerySqlGeneratorFactory
Microsoft.EntityFrameworkCore.Query.IRelationalSqlTranslatingExpressionVisitorFactory
Microsoft.EntityFrameworkCore.Query.ISqlExpressionFactory
Microsoft.EntityFrameworkCore.Query.IQueryTranslationPostprocessorFactory
Microsoft.EntityFrameworkCore.Query.IRelationalParameterBasedSqlProcessorFactory
Microsoft.EntityFrameworkCore.Query.INavigationExpansionExtensibilityHelper
Microsoft.EntityFrameworkCore.Query.IQueryableMethodTranslatingExpressionVisitorFactory
Microsoft.EntityFrameworkCore.Storage.IExceptionDetector
Microsoft.EntityFrameworkCore.Infrastructure.ISingletonOptions
Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal.ISqlServerSingletonOptions
Microsoft.EntityFrameworkCore.SqlServer.ValueGeneration.Internal.ISqlServerValueGeneratorCache
Microsoft.EntityFrameworkCore.SqlServer.Update.Internal.ISqlServerUpdateSqlGenerator
Microsoft.EntityFrameworkCore.SqlServer.ValueGeneration.Internal.ISqlServerSequenceValueGeneratorFactory      
Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.ISqlServerConnection
Microsoft.EntityFrameworkCore.Storage.IParameterNameGeneratorFactory
System.Collections.Generic.IComparer`1[Microsoft.EntityFrameworkCore.Update.IReadOnlyModificationCommand]     
Microsoft.EntityFrameworkCore.Migrations.IMigrationsIdGenerator
Microsoft.EntityFrameworkCore.Update.Internal.IRowKeyValueFactoryFactory
Microsoft.EntityFrameworkCore.Update.Internal.IRowForeignKeyValueFactoryFactory
Microsoft.EntityFrameworkCore.Update.Internal.IRowIndexValueFactoryFactory
Microsoft.EntityFrameworkCore.Update.Internal.IRowIdentityMapFactory
Microsoft.EntityFrameworkCore.Infrastructure.IModelCustomizer
Microsoft.EntityFrameworkCore.Infrastructure.IModelRuntimeInitializer
Microsoft.EntityFrameworkCore.Migrations.IMigrator
Microsoft.EntityFrameworkCore.Migrations.IMigrationCommandExecutor
Microsoft.EntityFrameworkCore.Migrations.IMigrationsAssembly
Microsoft.EntityFrameworkCore.Storage.IDatabase
Microsoft.EntityFrameworkCore.Update.IBatchExecutor
Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory
Microsoft.EntityFrameworkCore.Storage.IRawSqlCommandBuilder
Microsoft.EntityFrameworkCore.Update.ICommandBatchPreparer
Microsoft.EntityFrameworkCore.Migrations.IMigrationsModelDiffer
Microsoft.EntityFrameworkCore.Storage.ITypeMappingSource
Microsoft.EntityFrameworkCore.Storage.IDatabaseCreator
Microsoft.EntityFrameworkCore.Storage.IDbContextTransactionManager
Microsoft.EntityFrameworkCore.Query.IQueryContextFactory
Microsoft.EntityFrameworkCore.Storage.Internal.INamedConnectionStringResolver
Microsoft.EntityFrameworkCore.Storage.IDatabaseFacadeDependencies
Microsoft.EntityFrameworkCore.Storage.IRelationalDatabaseFacadeDependencies
Microsoft.EntityFrameworkCore.Diagnostics.IRelationalConnectionDiagnosticsLogger
Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger`1[Microsoft.EntityFrameworkCore.DbLoggerCategory+Database+Connection]
Microsoft.EntityFrameworkCore.Diagnostics.IRelationalCommandDiagnosticsLogger
Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger`1[Microsoft.EntityFrameworkCore.DbLoggerCategory+Database+Command]
Microsoft.EntityFrameworkCore.Diagnostics.IInterceptorAggregator
Microsoft.EntityFrameworkCore.Query.IShapedQueryCompilingExpressionVisitorFactory
Microsoft.EntityFrameworkCore.Query.IQueryTranslationPreprocessorFactory
Microsoft.EntityFrameworkCore.Metadata.IAdHocMapper
Microsoft.EntityFrameworkCore.Query.ISqlAliasManagerFactory
Microsoft.EntityFrameworkCore.Query.ILiftableConstantFactory
Microsoft.EntityFrameworkCore.Query.IRelationalLiftableConstantFactory
Microsoft.EntityFrameworkCore.Query.ILiftableConstantProcessor
Microsoft.EntityFrameworkCore.Storage.RelationalSqlGenerationHelperDependencies
Microsoft.EntityFrameworkCore.Storage.RelationalTypeMappingSourceDependencies
Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidatorDependencies
Microsoft.EntityFrameworkCore.Update.UpdateSqlGeneratorDependencies
Microsoft.EntityFrameworkCore.Metadata.RelationalAnnotationProviderDependencies
Microsoft.EntityFrameworkCore.Migrations.MigrationsAnnotationProviderDependencies
Microsoft.EntityFrameworkCore.Storage.ParameterNameGeneratorDependencies
Microsoft.EntityFrameworkCore.Storage.RelationalTransactionFactoryDependencies
Microsoft.EntityFrameworkCore.Storage.RelationalCommandBuilderDependencies
Microsoft.EntityFrameworkCore.Query.QuerySqlGeneratorDependencies
Microsoft.EntityFrameworkCore.Query.RelationalEvaluatableExpressionFilterDependencies
Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelDependencies
Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelRuntimeInitializerDependencies
Microsoft.EntityFrameworkCore.Query.RelationalLiftableConstantExpressionDependencies
Microsoft.EntityFrameworkCore.Migrations.MigrationsSqlGeneratorDependencies
Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure.RelationalConventionSetBuilderDependencies  
Microsoft.EntityFrameworkCore.Update.ModificationCommandBatchFactoryDependencies
Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparerDependencies
Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreatorDependencies
Microsoft.EntityFrameworkCore.Migrations.HistoryRepositoryDependencies
Microsoft.EntityFrameworkCore.Query.RelationalCompiledQueryCacheKeyGeneratorDependencies
Microsoft.EntityFrameworkCore.Query.RelationalMethodCallTranslatorProviderDependencies
Microsoft.EntityFrameworkCore.Query.RelationalAggregateMethodCallTranslatorProviderDependencies
Microsoft.EntityFrameworkCore.Query.RelationalMemberTranslatorProviderDependencies
Microsoft.EntityFrameworkCore.Query.SqlExpressionFactoryDependencies
Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitorDependencies
Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitorDependencies
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitorDependencies
Microsoft.EntityFrameworkCore.Query.RelationalQueryTranslationPreprocessorDependencies
Microsoft.EntityFrameworkCore.Query.RelationalQueryTranslationPostprocessorDependencies
Microsoft.EntityFrameworkCore.Query.RelationalParameterBasedSqlProcessorDependencies
Microsoft.EntityFrameworkCore.Storage.RelationalConnectionDependencies
Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseDependencies
Microsoft.EntityFrameworkCore.Query.RelationalQueryContextDependencies
Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextDependencies
Microsoft.EntityFrameworkCore.Metadata.RelationalAdHocMapperDependencies
Microsoft.EntityFrameworkCore.Infrastructure.IDbSetFinder
Microsoft.EntityFrameworkCore.Internal.IDbSetInitializer
Microsoft.EntityFrameworkCore.Internal.IDbSetSource
Microsoft.EntityFrameworkCore.Internal.IEntityFinderSource
Microsoft.EntityFrameworkCore.Query.IEntityMaterializerSource
Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure.IConventionSetBuilder
Microsoft.EntityFrameworkCore.Infrastructure.IModelCacheKeyFactory
Microsoft.Extensions.Logging.ILoggerFactory
Microsoft.EntityFrameworkCore.Infrastructure.IModelSource
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IInternalEntityEntrySubscriber
Microsoft.EntityFrameworkCore.ChangeTracking.IEntityEntryGraphIterator
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IEntityGraphAttacher
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IKeyPropagator
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.INavigationFixer
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ILocalViewListener
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IStateManager
Microsoft.EntityFrameworkCore.Infrastructure.IConcurrencyDetector
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IInternalEntityEntryNotifier
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IValueGenerationManager
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IChangeTrackerFactory
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IChangeDetector
Microsoft.EntityFrameworkCore.Internal.IDbContextServices
Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies
Microsoft.EntityFrameworkCore.Storage.IExecutionStrategy
Microsoft.EntityFrameworkCore.Query.Internal.ICompiledQueryCache
Microsoft.EntityFrameworkCore.Query.IAsyncQueryProvider
Microsoft.EntityFrameworkCore.Query.Internal.IQueryCompiler
Microsoft.EntityFrameworkCore.Internal.ISingletonOptionsInitializer
Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger`1[TLoggerCategory]
Microsoft.EntityFrameworkCore.Diagnostics.IInterceptors
Microsoft.EntityFrameworkCore.Diagnostics.ILoggingOptions
Microsoft.EntityFrameworkCore.Infrastructure.ICoreSingletonOptions
Microsoft.EntityFrameworkCore.Metadata.IModel
Microsoft.EntityFrameworkCore.Metadata.IDesignTimeModel
Microsoft.EntityFrameworkCore.Infrastructure.ICurrentDbContext
Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions
Microsoft.EntityFrameworkCore.Infrastructure.IResettableService
Microsoft.EntityFrameworkCore.Storage.ValueConversion.IValueConverterSelector
Microsoft.EntityFrameworkCore.Metadata.IConstructorBindingFactory
Microsoft.EntityFrameworkCore.Infrastructure.Internal.ILazyLoaderFactory
Microsoft.EntityFrameworkCore.Infrastructure.ILazyLoader
Microsoft.EntityFrameworkCore.Metadata.IParameterBindingFactories
Microsoft.EntityFrameworkCore.Metadata.Internal.IMemberClassifier
Microsoft.EntityFrameworkCore.Metadata.IPropertyParameterBindingFactory
Microsoft.EntityFrameworkCore.Metadata.IParameterBindingFactory
Microsoft.Extensions.Caching.Memory.IMemoryCache
Microsoft.EntityFrameworkCore.Update.IUpdateAdapterFactory
Microsoft.EntityFrameworkCore.Storage.Json.IJsonValueReaderWriterSource
Microsoft.EntityFrameworkCore.Diagnostics.IDbContextLogger
System.Diagnostics.DiagnosticSource
Microsoft.EntityFrameworkCore.Metadata.LazyLoaderParameterBindingFactoryDependencies
Microsoft.EntityFrameworkCore.Storage.DatabaseProviderDependencies
Microsoft.EntityFrameworkCore.Infrastructure.ModelSourceDependencies
Microsoft.EntityFrameworkCore.ValueGeneration.ValueGeneratorCacheDependencies
Microsoft.EntityFrameworkCore.Infrastructure.ModelValidatorDependencies
Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies
Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizerDependencies
Microsoft.EntityFrameworkCore.Infrastructure.ModelCacheKeyFactoryDependencies
Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverterSelectorDependencies
Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSourceDependencies
Microsoft.EntityFrameworkCore.Query.EvaluatableExpressionFilterDependencies
Microsoft.EntityFrameworkCore.Infrastructure.RuntimeModelDependencies
Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializerDependencies
Microsoft.EntityFrameworkCore.Query.NavigationExpansionExtensibilityHelperDependencies
Microsoft.EntityFrameworkCore.Storage.Json.JsonValueReaderWriterSourceDependencies
Microsoft.EntityFrameworkCore.Query.LiftableConstantExpressionDependencies
Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure.ProviderConventionSetBuilderDependencies    
Microsoft.EntityFrameworkCore.Query.QueryCompilationContextDependencies
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManagerDependencies
Microsoft.EntityFrameworkCore.Storage.ExecutionStrategyDependencies
Microsoft.EntityFrameworkCore.Query.CompiledQueryCacheKeyGeneratorDependencies
Microsoft.EntityFrameworkCore.Query.QueryContextDependencies
Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitorDependencies
Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessorDependencies
Microsoft.EntityFrameworkCore.Query.QueryTranslationPostprocessorDependencies
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitorDependencies
Microsoft.EntityFrameworkCore.ValueGeneration.ValueGeneratorSelectorDependencies
Microsoft.EntityFrameworkCore.Storage.DatabaseDependencies
Microsoft.EntityFrameworkCore.Infrastructure.ModelDependencies
Microsoft.EntityFrameworkCore.ModelCreationDependencies
Microsoft.EntityFrameworkCore.Metadata.AdHocMapperDependencies

严重注意:实体构造函数不能注入 IRegisteredServices  类型的服务,因为 EF Core 内部实现时,本身就是从 IRegisteredServices.Services 集合中查找可以注入的服务的,而 IRegisteredServices.Services 是不包含它自己的。说人话就是:用 IRegisteredServices 类注入是找不到该服务的。

然后解决第二个问题:在实体类的构造函数中注入服务有啥用?大多数时候没啥用,但当你要使用某些服务来获取特殊信息,或执行特殊操作(如在实体类中执行 SQL 语句)时就用得上。

咱们举个例子,就用官方文档最喜欢的 Blog 和 Post 实体来演示。其中,Blog 类的构造函数将注入 IEntityType 服务。然后可以利用这个服务来获取 Blog 实体有几个属性,有几个键,有几个导航属性。

public class Blog
{
    // 私有字段
    private IEntityType? _thisEntity;
    // 私有构造器
    private Blog(IEntityType t) => _thisEntity = t;

    // 公共构造器
    public Blog()
    {
    }

    public int BlogID { get; set; }
    public string DisplayName { get; set; } = string.Empty;
    public string Url { get; set; } = string.Empty;

    public List<Post> PostList { get; set; } = new();

    // 以下属性通过注入的 IEntityType 获取相关值
    public int PropertyCount => _thisEntity?.GetProperties().Count() ?? 0;
    public int NavigationCount => _thisEntity?.GetNavigations().Count() ?? 0;
    public int KeyCount => _thisEntity?.GetKeys().Count() ?? 0;
}

public class Post
{
    public int PostID { get; set; }
    public string Header { get; set; } = string.Empty;
    public Blog? TheBlog { get; set; }
}

注意,你自己 new 一个 Blog 实例是没有注入功能的,所以要定义一个无参数的公共构造函数,以供外部初始化用。另一个私有构造函数有一个 IEntityType 类型的参数,可以接收注入。因为这构造函数只由 EF Core 内部调用,代码中调用无法注入,故声明为私有即可。EF Core 在查找构造函数时,不管你是公有的还是私有的,只要不是静态的,一律能发现。

在访问 Blog 实体时就可以获取键、属性、导航属性的数量。

var q = c.Blogs.Include(b => b.PostList).ToArray();
var first = q.FirstOrDefault();
if (first != null)
{
    Console.WriteLine($"实体{first.GetType().Name}有{first.
PropertyCount}个属性,{first.KeyCount}个键,{first.
NavigationCount}个导航属性");
}

得到的输出如下:

除了构造函数,也可以从属性注入。例如

[PrimaryKey(nameof(Screen.ScrID))]
public class Screen
{
    [Column("scr_id")]
    public int ScrID { get; set; }
    [Column("width")]
    public int Width { get; set; }
    [Column("height")]
    public int Height { get; set; }

    //----------- 注意以下属性 --------------
    public MyDBContext? ThisContext { get; set; }
}

public class MyDBContext : DbContext
{
    public MyDBContext(DbContextOptions<MyDBContext> options)
        : base(options)
    { }
        
    public DbSet<Screen> Screens { get; set; }
}

上面示例中,MyDBContext 实例会注入到每个 Screen 实例的 ThisContext 属性。即每个实体实例的 ThisContext 属性都引用同一个 MyDBContext 对象。

var q = dc.Screens.FirstOrDefault();
if (q != null)
{
    if (q.ThisContext != null)
    {
        Console.WriteLine("ThisContext属性:{0}", q.ThisContext);
    }
}

// 输出:
// ThisContext属性:MyDBContext

好了,今天就水到这里了。因为这个主题确实太简单了,老周也不必举太多例子。