Database First MVC动态设置连接字符串遇'metadata不支持'错误
你遇到的问题本质上是对DbContext连接字符串的赋值逻辑理解偏差了——你把Entity Framework专用的实体连接字符串(带metadata、provider段的那种)直接赋值给了this.Database.Connection.ConnectionString,但这个属性只接受纯SQL Server的连接字符串(不含EF特定的metadata等内容),ADO.NET的SqlConnection根本不认识metadata这个关键字,所以才会抛出这个错误。
正确的解决方案分两种场景:
场景1:直接传入完整的实体连接字符串
如果调用方已经准备好了完整的带metadata的实体连接字符串,只需要修改DbContext的构造函数,把参数直接传给基类构造函数即可,不需要手动赋值Database.Connection.ConnectionString:
public partial class DevTS_mtEntities : DbContext { public DevTS_mtEntities(string conn) : base(conn) { // 基类会自动处理带metadata的实体连接字符串,无需额外操作 } }
调用示例:
var fullEntityConnString = "metadata=res://*/Setup.Questions.Questions.csdl|res://*/Setup.Questions.Questions.ssdl|res://*/Setup.Questions.Questions.msl;provider=System.Data.SqlClient;provider connection string=\"data source=myServer;initial catalog=DevTS_mt;user id=myUser;password=myPass;MultipleActiveResultSets=True;App=EntityFramework\""; using (var db = new DevTS_mtEntities(fullEntityConnString)) { // 正常执行数据库操作 }
场景2:动态替换连接字符串中的服务器、账号等参数
如果需要根据动态参数(比如用户输入、配置项)生成连接字符串,可以用SqlConnectionStringBuilder和EntityConnectionStringBuilder安全构建完整的实体连接字符串,再传给基类构造函数:
public partial class DevTS_mtEntities : DbContext { // 带动态参数的构造函数 public DevTS_mtEntities(string server, string database, string userId, string password) : base(BuildFullEntityConnectionString(server, database, userId, password)) { } // 辅助方法:构建完整的EF实体连接字符串 private static string BuildFullEntityConnectionString(string server, string database, string userId, string password) { // 第一步:构建纯SQL Server连接字符串 var sqlConnBuilder = new SqlConnectionStringBuilder { DataSource = server, InitialCatalog = database, UserID = userId, Password = password, MultipleActiveResultSets = true, // EF必需配置 ApplicationName = "EntityFramework" }; // 第二步:包装成EF专用的实体连接字符串 var entityConnBuilder = new EntityConnectionStringBuilder { // 这里的metadata路径要和你Database First生成的模型完全对应 Metadata = "res://*/Setup.Questions.Questions.csdl|res://*/Setup.Questions.Questions.ssdl|res://*/Setup.Questions.Questions.msl", Provider = "System.Data.SqlClient", ProviderConnectionString = sqlConnBuilder.ToString() }; return entityConnBuilder.ToString(); } }
调用示例:
using (var db = new DevTS_mtEntities("myServer", "DevTS_mt", "myUser", "myPass")) { // 正常执行数据库操作 }
为什么原来的代码会报错?
this.Database.Connection.ConnectionString对应的是底层ADO.NET SqlConnection的连接字符串,它只负责和SQL Server建立直接连接,不包含EF所需的模型元数据(metadata)、数据提供程序(provider)等信息。而你赋值的是EF专用的实体连接字符串,里面的metadata关键字对SqlConnection来说是无效的,所以会抛出“不支持该关键字”的错误。
内容的提问来源于stack exchange,提问作者Matt

