【EF Core】實體類的依賴注入
在使用外部模型那篇水文中,有大伙伴提出:老周,你那個 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}個導航屬性"); }
得到的輸出如下:
實體Blog有3個屬性,1個鍵,1個導航屬性
除了構造函數,也可以從屬性注入。例如
[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
好了,今天就水到這里了。因為這個主題確實太簡單了,老周也不必舉太多例子。

浙公網安備 33010602011771號