EF6结合Devart dotConnect for MySQL查询指向错误数据库求助
原因分析
EF6数据库优先模式下,EDMX生成时会将生成模型的数据库名(此处为entity_model)硬编码到模型的存储元数据中——具体体现在EDMX的StorageModels部分,每个实体对应的表会带上Schema="[数据库名]"属性,或者直接写成[数据库名].[表名]的形式。Devart dotConnect for MySQL解析EDMX时,会优先沿用这些硬编码的数据库名,即便你动态修改了连接字符串的Database属性,EF依然会使用元数据里的数据库前缀。
旧项目无此问题,是因为生成EDMX时未在存储模型中指定数据库名——可能是当时连接的是默认库,或是生成模型时Devart的相关设置不同,导致存储元数据里的表名不带数据库前缀。
解决方法
方法1:手动修改EDMX移除数据库名前缀
用文本编辑器或VS的XML编辑器打开EDMX文件,找到edmx:StorageModels节点下的EntityContainer,处理每个EntitySet:
- 若存在
Schema="entity_model"属性,直接删除该属性; - 若表名写成
[entity_model].[table1]格式,修改为[table1]。
保存后重新生成DbContext,此时DbSet生成的SQL就不会带数据库名前缀,会自动使用连接字符串指定的数据库。
方法2:生成EDMX时调整Devart设置
在Devart Entity Model Wizard的设置步骤中,取消勾选「Include database name in storage model」(不同版本的Devart选项 wording 可能略有差异),这样生成的EDMX存储模型就不会包含数据库名,后续动态切换连接字符串时,EF会自动采用连接字符串指定的库。
方法3:代码动态替换存储元数据中的数据库名
若不想手动修改EDMX,可在DbContext构造函数中通过代码替换硬编码的数据库名:
public class MyDbContext : DbContext { public MyDbContext(string connectionString) : base(connectionString) { var objectContext = ((IObjectContextAdapter)this).ObjectContext; var workspace = objectContext.MetadataWorkspace; var storageContainer = workspace.GetEntityContainer("ModelStoreContainer", DataSpace.SSpace); foreach (var entitySet in storageContainer.BaseEntitySets.OfType<EntitySet>()) { if (entitySet.Schema == "entity_model") { var targetDbName = this.Database.Connection.Database; entitySet.Schema = targetDbName; } } } }
该方法适合需动态适配不同数据库名的场景,无需修改EDMX,但需注意EF元数据的缓存问题,建议每次创建DbContext实例时执行这段逻辑。
验证方式
修改完成后调试时,查看DbSet的SQL语句,确认不再包含entity_model.前缀,此时查询会自动指向连接字符串指定的数据库。
内容的提问来源于stack exchange,提问作者SiscoKid

