3

我有一个应用程序具有多个DbContext共享连接字符串的子类(这是为了避免 EF 使用单个大DbContext类型的可怕启动时间)。在某些点(对我来说是可重复的,对其他人来说有些重复),我在尝试进行数据库查询时收到以下错误:

System.Data.EntityException:“底层提供程序在打开时失败。”
内部异常:
System.Data.SqlClient.SqlException“用户'用户名'登录失败”

如果我切换回使用单个 Giant ,问题似乎就消失了DbContext

有谁知道这意味着什么/如何解决它?如果我重复使用相同的DbConnection对象DbContexts(而不是只使用相同的连接字符串)会有帮助吗?该连接字符串已经成功地在同一个请求中进行了多次查询,因此不可能是凭据错误。

我正在使用 ASP.NET MVC 3、EF 4.3.1、.NET 4.0、VS 2010。

相关的堆栈跟踪如下:

 [SqlException (0x80131904): Login failed for user 'testing_net'.]
    System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +6351920
    System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +412
    System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1363
    System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK) +53
    System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout) +6366878
    System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) +6366793
    System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean  redirectedUserInstance) +352
    System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) +831
    System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) +49
    System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject) +6368598
    System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject) +78
    System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) +2194
    System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) +89
    System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) +6372110
    System.Data.SqlClient.SqlConnection.Open() +300
    System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection  storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure) +67

 [EntityException: The underlying provider failed on Open.]
    System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure) +11108990
    System.Data.EntityClient.EntityConnection.Open() +142
    System.Data.Objects.ObjectContext.EnsureConnection() +97
    System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +57
    System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +47
    System.Linq.Enumerable.Single(IEnumerable`1 source) +156

代码的大致轮廓如下:

// db context:
public class MyDbContext<T> : DbContext {
    public MyDbContext(string connectionString) : base(connectionString) { }

    protected override OnModelCreating(DbModelBuilder builder)
    {
        // constructs the model base on the type of T
        // code first POCO entities are annotated with an attribute that links
        // them to one or more types T
    }
}

我使用 AutoFac 的 DI 将我的 DbContext 注入到我的数据访问层的服务中。上下文的生命周期是 HttpRequest 的长度。

实际的异常发生在对 Queryable.Single() 的调用上。

编辑:我认为这个问题可能是相关的,但我不确定如何理解所描述的竞争条件。

编辑:既然我理解了这个问题,我可以发布有问题的代码:

MyDbContext<T1> db1 = ...
var connectionString = db1.Database.Connection.ConnectionString; 
var dbContext2 = new MyDbContext<T2>(connectionString);
4

2 回答 2

7

事实证明,问题与 PersistSecurityInfo 连接字符串属性有关。来自 MSDN:

PersistSecurityInfo:获取或设置一个布尔值,该值指示在连接打开或曾经处于打开状态时是否不将安全敏感信息(例如密码)作为连接的一部分返回。

我的连接字符串最初有一个用户名和密码。我会用这个字符串初始化一个 DbContext,然后在初始上下文的 Database.Connection 属性中使用相同的字符串初始化一个不同的上下文。但是,由于 PersistSecurityInfo 设置为 false,因此在某些情况下,密码会从连接对连接字符串的引用中悄然消失,从而导致新 DbContext 实例上的登录失败。

我想到的可能解决方案是: 1. 将 PersistSecurityInfo 设置为 true 2. 保留对连接字符串的单独引用并使用它 3. 使用不将用户名和密码放入连接的不同形式的身份验证细绳

于 2012-10-01T23:50:15.380 回答
0

据我所知,用户应该有一些角色,即 db_datareader、db_datawriter、db_ddladmin、db_owner 或 db_securityadmin。更多角色信息请参考:

http://msdn.microsoft.com/en-us/library/ms189121(v=SQL.105).aspx

于 2021-12-17T13:09:51.640 回答