2.一致性:确保每个 DbContext 实例使用相同的模型配置。
dotnet ef dbcontext optimize这将生成 DbContext 的预编译模型。我只有一个 POCO 类,生成了 3 个文件,类名称就是文件名称。
[DbContext(typeof(DataContext))] public partial class DataContextModel : RuntimeModel { static DataContextModel() { var model = new DataContextModel(); model.Initialize(); model.Customize(); _instance = model; } private static DataContextModel _instance; public static IModel Instance => _instance; partial void Initialize(); partial void Customize(); } public partial class DataContextModel { partial void Initialize() { var deviceDatum = DeviceDatumEntityType.Create(this); DeviceDatumEntityType.CreateAnnotations(deviceDatum); AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); AddAnnotation("ProductVersion", "8.0.0-rc.2.23480.1"); AddAnnotation("Relational:MaxIdentifierLength", 63); AddRuntimeAnnotation("Relational:RelationalModel", CreateRelationalModel()); } private IRelationalModel CreateRelationalModel() { // 这里面非常多描述类型的代码,节约篇幅我就不写全了。 var relationalModel = new RelationalModel(this); var deviceDatum = FindEntityType("AspireSample.DeviceDatum")!; var defaultTableMappings = new List<TableMappingBase<ColumnMappingBase>>(); deviceDatum.SetRuntimeAnnotation("Relational:DefaultMappings", defaultTableMappings); .... return relationalModel.MakeReadOnly(); } } internal partial class DeviceDatumEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { var runtimeEntityType = model.AddEntityType( "AspireSample.DeviceDatum", typeof(DeviceDatum), baseEntityType); var id = runtimeEntityType.AddProperty( "Id", typeof(string), propertyInfo: typeof(DeviceDatum).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), fieldInfo: typeof(DeviceDatum).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly), afterSaveBehavior: PropertySaveBehavior.Throw); id.TypeMapping = StringTypeMapping.Default.Clone( comparer: new ValueComparer<string>( (string v1, string v2) => v1 == v2, (string v) => v.GetHashCode(), (string v) => v), keyComparer: new ValueComparer<string>( (string v1, string v2) => v1 == v2, (string v) => v.GetHashCode(), (string v) => v), providerValueComparer: new ValueComparer<string>( (string v1, string v2) => v1 == v2, (string v) => v.GetHashCode(), (string v) => v), mappingInfo: new RelationalTypeMappingInfo( dbType: System.Data.DbType.String)); ...... var key = runtimeEntityType.AddKey( new[] { id }); runtimeEntityType.SetPrimaryKey(key); return runtimeEntityType; } public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { runtimeEntityType.AddAnnotation("Relational:FunctionName", null); runtimeEntityType.AddAnnotation("Relational:Schema", null); runtimeEntityType.AddAnnotation("Relational:SqlQuery", null); runtimeEntityType.AddAnnotation("Relational:TableName", "devicedata"); runtimeEntityType.AddAnnotation("Relational:ViewName", null); runtimeEntityType.AddAnnotation("Relational:ViewSchema", null); Customize(runtimeEntityType); } static partial void Customize(RuntimeEntityType runtimeEntityType); }可以看到,优化工具帮我们生成了非常多的代码,尤其是与类型描述相关的代码,因此,如果我们修改模型,那么必须重新执行一遍对应的生成指令。
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { // 堆代码 duidaima.com // 指定编译模型的使用 optionsBuilder.UseModel(CompiledModels.MyCompiledModel.Instance); } }权衡利弊
提升启动速度,对实体类型较多的 DbContext 尤其显著。
2.每次修改模型都必须重新生成优化代码。