Identity框架无法连接Azure远程数据库,始终连接本地数据库问题
我正在使用Identity框架和ASP.NET MVC5(数据库优先模式)。本地环境下一切正常,但Identity无法连接我部署在Azure上的远程数据库。我的web.config中的连接字符串如下:
<!-- 本地数据库 --> <add name="MyEntities" connectionString="metadata=res://*/EntityDataModel.csdl|res://*/EntityDataModel.ssdl|res://*/EntityDataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=MY-PC\SQLEXPRESS;Initial Catalog=MyLocalDBName;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /> <!-- 远程数据库 --> <add name="MyEntities" connectionString="metadata=res://*/EntityDataModel.csdl|res://*/EntityDataModel.ssdl|res://*/EntityDataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=tcp:MyServerName.database.windows.net,1433;initial catalog=MyRemoteDBName;persist security info=False;user id=MyID;password=MyPassword;connect timeout=30;encrypt=True;trustservercertificate=False;application name=EntityFramework;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
(当我想使用远程数据调试时,会注释本地数据库连接字符串,反之亦然)
奇怪的是,Identity始终连接本地数据库(首次启动应用时甚至会在本地创建名为MyRemoteDBName的新数据库),但Entity Framework却能正确连接远程数据库并显示远程数据!
我的IdentityModels.cs中有如下类:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext() : base("MyLocalDBName", throwIfV1Schema: false) { } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } }
我猜测问题出在public ApplicationDbContext() : base("MyLocalDBName", throwIfV1Schema: false)这一行?我尝试将MyLocalDBName替换为MyRemoteDBName,但MyRemoteDBName还是会在本地创建(?!)
为何Identity始终连接本地数据库,而Entity Framework却能正常连接远程数据库?
编辑补充:以下是我实例化ApplicationDbContext的方式:
ApplicationDbContext context = new ApplicationDbContext(); var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context)); var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
问题根源与解决步骤
嘿,你猜的完全没错!问题确实出在ApplicationDbContext的构造函数里,但不是简单替换数据库名称那么简单——这里的关键是Identity框架对连接字符串的处理逻辑和你常规EF的用法不一样!
1. 核心问题解析
当你给IdentityDbContext的构造函数传入一个字符串(比如"MyLocalDBName")时,它默认会去查找同名的SqlClient类型连接字符串,如果找不到,就会自动生成一个指向本地SqlExpress的连接字符串(这就是为什么你替换成MyRemoteDBName后,本地会新建这个数据库的原因)。而你在web.config里定义的MyEntities是EntityClient类型的连接字符串(对应你的EDM模型),Identity根本不会识别它!
2. 解决方法:指定连接字符串名称
把ApplicationDbContext构造函数里的参数改成你web.config里的连接字符串名称"MyEntities",这样Identity就会直接使用当前启用的那个(本地/远程)连接字符串:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext() : base("MyEntities", throwIfV1Schema: false) { } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } }
3. 额外检查事项
- 确保切换本地/远程时,只注释其中一个
MyEntities连接字符串,不要让两个同名的连接字符串同时存在(web.config里同名配置项会被后面的覆盖,但注释掉一个就不会有冲突)。 - 检查发布配置(比如
Web.Release.config)有没有设置连接字符串替换规则,导致远程环境下被意外改回本地配置。 - 确认代码里没有其他硬编码的本地连接信息,比如
Create方法有没有手动指定连接字符串。
为什么常规EF能正常工作?
因为你业务逻辑里使用的是MyEntities这个EntityClient连接字符串(对应你的EDM模型),EF会直接读取这个配置;而Identity默认走的是SqlClient连接字符串的逻辑,所以才会和你的常规EF行为不一致。
内容的提问来源于stack exchange,提问作者user2687153

