gpt4 book ai didi

c# - 禁用 EF Core 的包含所有属性的约定

转载 作者:行者123 更新时间:2023-12-04 12:26:06 27 4
gpt4 key购买 nike

EF Core(就像之前的EF)自动添加properties with a get/set到模型。

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

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

如何禁用此约定?

最佳答案

在ConventionSet 对象中调用DbContext.OnModelCreating 之前,EF Core 会收集将应用的约定,并且传递给 OnModelCreating 的 ModelBuilber 将已经包含由约定发现的实体和属性。
然而,约定并不仅仅代表“一开始就做一次然后忘记它们”的规则来确定模型,每当您使用 Fluent API 更改模型时,它们都会不断应用。如果手动添加实体,此时会执行发现属性等的约定,并且模型始终保持最新。
ConventionSet 对象定义了一个“事件”列表,比如“添加的实体类型”,以及每个事件要执行的约定。
其中一个事件是“ModelInitialized”,它在开始时运行以通过 DbSetFindingConvention 初始识别实体。但是,此约定找到的每个实体类型都会触发“事件”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;
}

}
替换 DbContext 类中 DI 服务的默认实现(例如):
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {  
optionsBuilder.ReplaceService<Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure.IProviderConventionSetBuilder, TechnicalUtilities.CustomSqlServerConventionSetBuilder>();

}
或者,如果您想避免将此覆盖数据库提供程序设为特定,您还可以子类化 RuntimeConventionSetBuilder,覆盖 CreateConventionSet 方法,并将其注册到服务 IConventionSetBuilder。但该界面在 future 更有可能发生变化。
可以在此处找到公约的实现情况:
https://github.com/dotnet/efcore/blob/main/src/EFCore/Metadata/Conventions/
文档可以在这里找到:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.conventions?view=efcore-5.0
您应该检查特定约定实现了哪些“事件”,如果约定被取消,通常应该从每个“事件”中删除它。
这对 EF Core 5.0 有效,在以前的版本中可能有所不同。你也可以看看 https://github.com/dotnet/efcore/issues/5737#issuecomment-225724598

关于c# - 禁用 EF Core 的包含所有属性的约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43511861/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com