C# SqlCommand.ExecuteReader是否自动打开数据库连接?

C# SqlCommand.ExecuteReader是否自动打开数据库连接?,c#,javascript,wcf,json,sqldatareader,C#,Javascript,Wcf,Json,Sqldatareader,我注意到我的网页上有一些奇怪的行为。我有一个WCF数据服务,它提供JSON来填充jqGrid。使用javascript/ajax调用该服务 然后我有一些服务器端代码,它也调用相同的WCF服务来获取数据 在我的WCF服务中,我运行cmd.ExecuteReader()时没有事先打开的连接,在某些情况下,它不会抱怨连接——这似乎是在我从javascript调用数据服务时发生的。然而,当我从代码隐藏(即服务器端)调用该服务时,我得到一个错误,即“ExecuteReader需要一个开放的可用连接” 有人

我注意到我的网页上有一些奇怪的行为。我有一个WCF数据服务,它提供JSON来填充jqGrid。使用javascript/ajax调用该服务

然后我有一些服务器端代码,它也调用相同的WCF服务来获取数据

在我的WCF服务中,我运行cmd.ExecuteReader()时没有事先打开的连接,在某些情况下,它不会抱怨连接——这似乎是在我从javascript调用数据服务时发生的。然而,当我从代码隐藏(即服务器端)调用该服务时,我得到一个错误,即“ExecuteReader需要一个开放的可用连接”

有人知道这个问题吗?我尽可能缩小了范围。看起来唯一的区别在于我是从客户端还是从服务器端调用服务。这是我的密码:

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class JsonService
{
    static String _connection = ConfigMgr.ConnectionStrings["MyConnStr"];
    static DomainEntities dbContext = new DomainEntities(_connection);

    [OperationContract]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest,
                         RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    public JsonGrid Get()
    {
        return new JsonGridContract(dbContext.Products.ToJson()); 
    }
}
下面是调用ExecuteReader()的地方。它截取提供程序,将表达式树转换为SQL,然后执行它,将结果解析为基于字符串的JSON,而不是域对象

    public static List<JsonRow> ToJson(this IQueryable queryable)
    {
        Expression expression = queryable.Expression;
        expression = Evaluator.PartialEval(expression);

        if !(queryable.Provider is JsonQueryProvider)
              throw new InvalidOperationException("Provider is invalid");

        String table = (queryable.Provider as JsonQueryProvider).Table; 

        SqlConnection connection = (queryable.Provider as JsonQueryProvider).Connection; 

        Type elementType = TypeSystem.GetElementType(expression.Type);

        TranslateResult result = new QueryTranslator(table).Translate(expression);

        SqlCommand cmd = connection.CreateCommand();

        cmd.CommandText = result.CommandText;

        SqlDataReader reader = cmd.ExecuteReader();

        List<JsonRow> jsonResult = new List<JsonRow>(); 

        while (reader.Read())
            {
                JsonRow instance = new JsonRow(reader.FieldCount); 

                for (int i = 0, n = reader.FieldCount; i < n; i++)
                {
                    var items = instance.Items; 

                    if (reader.IsDBNull(i))
                    {
                        items[i] = string.Empty;  
                    }
                    else
                    {
                        items[i] = reader[i].ToString(); 
                    }
                }

                jsonResult.Add(instance); 
            }

        reader.Close(); 

        return jsonResult; 
    }

首先要排除的是,您不处理任何对象。 SqlCommand、SqlConnection和SqlDataReader都应该使用stmt块。 那你就不需要明确的结束了。看看这是否会全面失败。我很好奇垃圾收集器是否还没有收集到杀死你的连接对象

using(SqlConnection connection = new SqlConnection(...))
{
...
}

首先要排除的是,您不处理任何对象。 SqlCommand、SqlConnection和SqlDataReader都应该使用stmt块。 那你就不需要明确的结束了。看看这是否会全面失败。我很好奇垃圾收集器是否还没有收集到杀死你的连接对象

using(SqlConnection connection = new SqlConnection(...))
{
...
}

问题是您的SqlReader在使用连接时会占用连接。您不能将连接用于任何其他用途(例如执行另一个读取器,甚至另一条语句)。在读卡器关闭之前,您的连接基本上是锁定的

通常,如Adam所说,将您的语句包装在using块中,您的问题就会得到解决。但是,我注意到您似乎正在从某种缓存(queryable.Provider)中获取连接。如果您试图重复使用连接或缓存连接,您将遇到相同的问题


如果您想利用ADO.NET的连接池功能,您需要在using块中创建一个新的连接实例,并且只重用完全相同的连接字符串。ADO.NET将自动汇集基础连接资源。

问题是,您的SqlReader将在使用连接时保持连接被占用。您不能将连接用于任何其他用途(例如执行另一个读取器,甚至另一条语句)。在读卡器关闭之前,您的连接基本上是锁定的

通常,如Adam所说,将您的语句包装在using块中,您的问题就会得到解决。但是,我注意到您似乎正在从某种缓存(queryable.Provider)中获取连接。如果您试图重复使用连接或缓存连接,您将遇到相同的问题

如果您想利用ADO.NET的连接池功能,您需要在using块中创建一个新的连接实例,并且只重用完全相同的连接字符串。ADO.NET将自动汇集基础连接资源