Entity framework,代码优先:避免不必要的连接到 azure master 数据库

Entity framework, code first : Avoid unwanted connections to the azure master database

当 EF 尝试连接到 Azure sql 数据库时(可能在尝试打开与数据库的连接时,不确定)它尝试 connect/login 到 master 数据库,问题是为什么?

不允许连接字符串上的用户连接到 master 数据库,从我看到的记录来看,EF 尝试使用该用户登录 master 数据库失败时出现错误,但应用程序在功能上正常运行(该应用不需要访问主数据库即可执行任何操作)。

根据我的研究,它似乎与 this issue 最相似,但由于无法重现而已关闭,我不确定在尝试获取 ProviderManifestToken 时是否会发生这种情况。

如果数据库用户对其所需的数据库具有正确的权限,并且连接字符串反映了这一点,为什么 EF 会尝试连接到 master 数据库?

上下文的示例连接字符串

Server=tcp:MyServer;Database=MyDb;User ID=MyDatabaseUser;Password=*****;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;TrustServerCertificate=False;

记录以下错误消息:

15-05-07 04:06:16.404 System.Data.SqlClient.SqlException (0x80131904): The server principal "MyDatabaseUser" is not able to access the database "master" under the current security context.
Database 'master' on server 'MyServer' is not currently available.  Please retry the connection later.  If the problem persists, contact customer support, and provide them the session tracing ID of '69955F47-7746-41560-A03C-807FB9A56478A'.
Login failed for user 'MyDatabaseUser'.
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK)
   at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover)
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
   at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection connection, DbInterceptionContext interceptionContext)
   at System.Data.Entity.SqlServer.SqlProviderServices.<>c__DisplayClass33.<UsingConnection>b__32()
   at System.Data.Entity.Infrastructure.DbExecutionStrategy.<>c__DisplayClass1.<Execute>b__0()
   at System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func`1 operation)
ClientConnectionId:5a5e2892-0d1f-471c-a1b7-5f9e5705655f1
ErrorCode: 916
ErrorCode: 40613
ErrorCode: 18456

Entity Framework 正在尝试连接到 master 数据库,因为 Code First 会尝试为项目创建数据库(如果它不存在)。这只能从 master.

完成

您仍然可以使用 Code First 并针对现有数据库进行操作,但您至少需要更改设置,这样它就不会尝试创建数据库。您可以将其设置为更新,这很好。我个人的偏好是关闭所有数据库管理,自己处理。

这是通过在 DbContext 上创建静态重载构造函数来完成的:

public static MyContext() : base(null) {}

This link discusses the different database initializers that are available. The above static constructor creates no initializer. Here 是另一个 link,它讨论了相同的初始化器,以及创建自定义初始化器。