使用ElasticContext EF进行连接池管理

时间:2016-11-24 12:13:27

标签: c# sql-server entity-framework connection-pooling azure-elastic-scale

在遵循Microsoft的一些示例后,我实现了DbContext的Elastic版本,该版本从Elastic ShardMapManager获取其连接字符串,具体取决于当前用户Tenant(或Customer)Id。

这在技术上有效,我已将其部署到我的Azure帐户。我现在担心的是连接池管理,我已经覆盖了默认的上下文连接创建机制。此外,我不确定每次请求shardMap.OpenConnectionForKey时都会如何管理连接(请参阅下面的我的ninject设置)。

昨天经过一些轻量级测试后,我的网络应用程序失败并显示以下消息:

  

超时已过期。从池中获取连接之前经过的超时时间。这可能是因为所有池连接都在使用中并且达到了最大池大小。

这可能是一次性的,因为我今天无法重新创建它但是我想确保连接池被有效地使用,因为我想要的最后一件事就是发生了当真正的用户开始锤击系统时。

它失败的代码在下面的ElasticScaleContext的完整代码中进行了评论:

public class ElasticScaleContext<T> : DbContext
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="shardMapManager">This is injected - only one of these exists per Application (Singleton)</param>
    /// <param name="customerId">The Shard Key is the Customer Id</param>
    /// <param name="shardConnectionString">The connection string for the Shard - this should only have the credentials and NOT any datasource. The correct datasource and initial catalog are returned by the Shard Map</param>
    /// <param name="metadataWorkSpaceConnectionString">Metadata required by EF model first cannot be passed in the shard connection string, it is passed here and used to return the MetadataWorkspace - no actual connection is created</param>
    public ElasticScaleContext(ShardMapManager shardMapManager, IPrincipal user, string shardConnectionString, string metadataWorkSpaceConnectionString)
      : base(CreateEntityConnection(shardMapManager, user, shardConnectionString, metadataWorkSpaceConnectionString), true)
    {
    }

    private static DbConnection CreateEntityConnection(ShardMapManager shardMapManager, IPrincipal user, string shardConnectionString, string metadataWorkSpaceConnectionString)
    {

        int shardKey = 0; // Default just to get a valid connection string on login page (it's never actually used)

        if (user != null && user.Identity.IsAuthenticated)
        {
            shardKey = user.Identity.GetCustomerId();
        }

        // Loads the Shard Map from the Shard Manager
        // This has the details of which shards are located on which databases
        ListShardMap<T> shardMap = shardMapManager.GetListShardMap<T>(AppConfig.ShardMapName);

        // No initialization
        Database.SetInitializer<ElasticScaleContext<T>>(null);

        // Create Elastic Scale SqlConnection
        // ******* FAILED HERE *********
        var shardConnection = shardMap.OpenConnectionForKey(shardKey, shardConnectionString, ConnectionOptions.None);

        // Allocate metadata workspace via an EF connection 
        var efConnection = new EntityConnection(metadataWorkSpaceConnectionString);

        // Create Entity connection that holds the sharded SqlConnection and metadata workspace
        var workspace = efConnection.GetMetadataWorkspace();
        EntityConnection entcon = new EntityConnection(workspace, shardConnection);

        return entcon;

    }

}

我正在使用Ninject,并将ShardMapManager注入为Singleton:

// Only ever create one Shard Map Manager
kernel.Bind<ShardMapManager>().ToMethod(context =>
{
   return ShardMapManagerFactory.GetSqlShardMapManager(AppConfig.ConnectionString, ShardMapManagerLoadPolicy.Lazy);
}).InSingletonScope();

并根据请求创建Context:

kernel.Bind<DbContext>().ToMethod(ctx =>
{
   return new ElasticScaleContext<int>(kernel.Get<ShardMapManager>(), kernel.Get<IPrincipal>(), AppConfig.BaseConnectionString, AppConfig.SCSMetaDataConnectionString);
}}).InRequestScope();

所以有几个问题:

  
      
  1. 我在上下文中创建的连接是否应该正常处理?

  2.   
  3. 有谁知道如何管理ShardMapManger连接?

  4.   
  5. 下面的代码可能是必要的(因为我的 Model First EF   方法)打开然后不关闭连接?

  6.   

UPDATE - 在@Evk的建议之后(参见注释)我修改了对EntityConnection的构造函数调用,以便为entityConnectionOwnsStoreConnection传递true,这应该允许它在使用后正确关闭存储连接, 见下文。我真的需要一种监视连接池的方法,看看它是否有任何影响:

 var efConnection = new EntityConnection(metadataWorkSpaceConnectionString);

  // Create Entity connection that holds the sharded SqlConnection and metadata workspace
  var workspace = efConnection.GetMetadataWorkspace();
  EntityConnection entcon = new EntityConnection(workspace, shardConnection. true);
  

最后,有没有办法监视和查看Azure Elastic SQL Pool上的连接的当前状态?

我意识到这是很多问题,但是我正在追踪这方面的任何信息 - 网上现有的信息确实不多。

  

其他信息:   该解决方案使用 EF6,SQL Server 2014,MVC 5.0

1 个答案:

答案 0 :(得分:1)

正如在注释中所指出的那样,在CreateEntityConnection方法中,您可以从底层连接创建EntityConnection,但不要设置重要参数&#34; entityConnectionOwnsStoreConnection&#34;为真。这意味着实体连接不负责管理您的商店连接,也不会关闭它,因此您的连接将泄漏。要修复,请使用另一个EntityConnection构造函数:

var entcon = new EntityConnection(workspace, shardConnection, true);

然后,当处理上下文时,它将处置您的EntityConnection,而{{1}}将处理基础数据库连接。