我注意到我的网页上出现了一些奇怪的行为。我有一个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;
}
如前所述,即使我从未打开连接,此方法也会正常运行。我正在使用AJAX客户端,
$.ajax(
{
type: "POST",
contentType: "application/json; charset=utf-8",
url: "Services/JsonService.svc/Get",
data: {},
dataType: "json",
success: function (data, textStatus) {
if (textStatus == "success") {
var thegrid = $("#jqGrid")[0];
thegrid.addJSONData(data.d);
}
},
error: function (data, textStatus) {
alert('An error has occured retrieving data.');
}
});
}
答案 0 :(得分:3)
要排除的第一件事是,您不会丢弃任何对象。 您的SqlCommand,SqlConnection和SqlDataReader都应该使用stmt块。 那你不需要明确的关闭。看看这是否全面失败。我很好奇,如果它只是垃圾收集器还没有收集到杀死你的连接对象。
using(SqlConnection connection = new SqlConnection(...))
{
...
}
答案 1 :(得分:0)
问题是您的SqlReader会在使用时保持Connection占用。您不能将连接用于其他任何事情(例如执行其他阅读器,甚至是其他语句)。在阅读器关闭之前,您的连接基本上已被锁定。
通常,就像Adam说的那样,将你的语句包装在一个使用块中,你的问题就会得到解决。但是,我注意到你似乎从某种缓存中获取连接(queryable.Provider)。如果您试图重复使用您的连接或缓存它,您将遇到同样的问题。
如果要利用ADO.NET的连接池功能,则需要在using块中创建一个新的Connection实例,并且只重用EXACT相同的连接字符串。 ADO.NET将自动汇集底层连接资源。