EF Seed方法首次执行报错:重置连接致登录失败,求解决方案
解决EF Seed首次执行ALTER DATABASE导致的登录失败问题
我太懂你这个头疼的问题了——首次跑Seed改数据库排序规则就炸出登录失败的错误,第二次执行又一切正常,还只能在Seed里解决、不能用自定义迁移。咱们来一步步捋清楚原因和解决方案:
问题根源
你用TransactionalBehavior.DoNotEnsureTransaction避开了“ALTER不能在多语句事务内执行”的限制,但修改数据库排序规则会触发数据库重置当前连接的状态。EF上下文此时持有的连接已经失效,后续执行AddOrUpdate时复用这个失效连接,就会抛出登录失败、会话终止的错误。第二次执行时数据库已经完成排序规则修改,连接状态稳定,所以就正常了。
解决方案:分离ALTER操作与后续Seed逻辑
核心思路是用独立连接执行ALTER语句,别污染EF上下文的原有连接,之后重置上下文的连接状态,确保后续操作能用有效连接。修改后的代码如下:
using System.Data; using System.Data.SqlClient; protected override void Seed(Repositories.EntityFramework.ApplicationDbContext context) { // 1. 用独立连接执行ALTER DATABASE,不影响原上下文的连接 var dbName = context.Database.Connection.Database; using (var separateConnection = new SqlConnection(context.Database.Connection.ConnectionString)) { separateConnection.Open(); var alterCommandText = $"ALTER DATABASE [{dbName}] COLLATE Latin1_General_100_CI_AS"; using (var command = new SqlCommand(alterCommandText, separateConnection)) { command.ExecuteNonQuery(); } separateConnection.Close(); } // 2. 重置原上下文的连接,确保后续操作拿到新鲜的有效连接 if (context.Database.Connection.State == ConnectionState.Open) { context.Database.Connection.Close(); } context.Database.Connection.Open(); // 3. 正常执行后续的Seed操作 context.Roles.AddOrUpdate( role => role.Name, new ApplicationRole() { Name = RoleConstants.SystemAdministrator } ); context.SaveChanges(); }
为什么这样有效?
- 独立连接执行ALTER:修改排序规则的操作完全在单独的连接里完成,执行完直接关闭,不会干扰EF上下文原本的连接状态。
- 重置上下文连接:关闭再重新打开上下文的连接,让EF获取到修改排序规则后的有效数据库连接,后续的
AddOrUpdate和SaveChanges就能正常跑,不会再触发登录失败的问题。
这样改完之后,首次Seed就能一次性成功,再也不用跑两次啦!
内容的提问来源于stack exchange,提问作者Ogglas
相关产品推荐
相关产品推荐

