ExecuteReader를 사용하려면 열려 있고 사용 가능한 연결이 필요합니다.연결의 현재 상태는 연결 중입니다.
ASP.NET 온라인을 통해 MSSQL 데이터베이스에 연결하려고 하면 두 명 이상이 동시에 연결할 때 다음 메시지가 나타납니다.
ExecuteReader를 사용하려면 열려 있고 사용 가능한 연결이 필요합니다.연결의 현재 상태는 연결 중입니다.
내 로컬 호스트 서버에서 사이트가 정상적으로 작동합니다.
이것은 대략적인 코드입니다.
public Promotion retrievePromotion()
{
int promotionID = 0;
string promotionTitle = "";
string promotionUrl = "";
Promotion promotion = null;
SqlOpenConnection();
SqlCommand sql = SqlCommandConnection();
sql.CommandText = "SELECT TOP 1 PromotionID, PromotionTitle, PromotionURL FROM Promotion";
SqlDataReader dr = sql.ExecuteReader();
while (dr.Read())
{
promotionID = DB2int(dr["PromotionID"]);
promotionTitle = DB2string(dr["PromotionTitle"]);
promotionUrl = DB2string(dr["PromotionURL"]);
promotion = new Promotion(promotionID, promotionTitle, promotionUrl);
}
dr.Dispose();
sql.Dispose();
CloseConnection();
return promotion;
}
무엇이 잘못되었는지 그리고 어떻게 고치는지 알 수 있을까요?
편집: 제 연결 문자열과 연결이 모두 정적인 것을 잊지 마십시오.저는 이것이 이유라고 생각합니다.조언 부탁드립니다.
public static string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
public static SqlConnection conn = null;
애초에 댓글만 달아서 죄송합니다만, ADO.NET 기능을 DB-Class(10년 전의 저)로 캡슐화하는 것이 현명할 것이라고 생각하는 사람들이 많아서 거의 매일 비슷한 댓글을 올립니다.대부분 정적/공유 개체를 사용하기로 결정하는데, 이는 어떤 작업에 대해서도 새 개체를 만드는 것보다 더 빠른 것처럼 보이기 때문입니다.
그것은 성능 측면에서도, 고장 안전 측면에서도 좋은 생각이 아닙니다.
Connection-Pool 영역을 밀렵하지 않음
ADO.NET이 ADO-NET Connection-Pool에서 DBMS에 대한 기본 연결을 내부적으로 관리하는 데는 충분한 이유가 있습니다.
실제로 대부분의 응용 프로그램은 연결에 하나 또는 몇 가지 다른 구성만 사용합니다.즉, 응용프로그램 실행 중에 많은 동일한 연결이 반복적으로 열리고 닫힙니다.ADO.NET은 연결을 여는 비용을 최소화하기 위해 연결 풀링이라는 최적화 기술을 사용합니다.
연결 풀링은 새 연결을 열어야 하는 횟수를 줄입니다.풀러는 물리적 연결의 소유권을 유지합니다.지정된 각 연결 구성에 대해 활성 연결 집합을 유지하여 연결을 관리합니다.사용자가 연결에서 열기를 호출할 때마다 풀러는 풀에서 사용 가능한 연결을 찾습니다.풀링된 연결을 사용할 수 있는 경우 새 연결을 여는 대신 해당 연결을 호출자에게 반환합니다.응용 프로그램이 연결에서 닫기를 호출하면 풀러는 해당 연결을 닫는 대신 풀링된 활성 연결 집합으로 반환합니다.연결이 풀로 반환되면 다음 열기 호출 시 다시 사용할 수 있습니다.
따라서 연결은 실제로 만들어지거나 열리거나 닫히는 것이 아니기 때문에 생성, 열거나 닫히는 것을 피할 이유가 없습니다.이것은 연결 풀이 연결을 재사용할 수 있는지 여부를 알 수 있는 "전용" 플래그입니다.그러나 연결이 "사용 중"(연결 풀에서 가정)인 경우 DBMS에 새로운 물리적 연결을 열어야 하기 때문에 매우 비용이 많이 들기 때문에 이 플래그는 매우 중요합니다.
따라서 성능이 향상되는 것이 아니라 그 반대입니다.지정된 최대 풀 크기(기본값 100)에 도달하면 예외(열린 연결이 너무 많음...)가 발생할 수도 있습니다.따라서 이는 성능에 큰 영향을 미칠 뿐만 아니라 심각한 오류의 원인이 되고 (트랜잭션을 사용하지 않고) 데이터 덤프 영역이 될 수 있습니다.
정적 연결을 사용하는 경우에도 이 개체에 액세스하려는 모든 스레드에 대해 잠금이 만들어집니다. ASP.NET은 기본적으로 멀티스레딩 환경입니다.따라서 성능 문제를 유발하는 이러한 잠금 장치가 있을 가능성이 높습니다.실제로 조만간 다양한 예외가 발생할 것입니다(예: ExecuteReader에 사용 가능한 개방형 연결이 필요한 경우).
결론:
- 연결이나 ADO.NET 개체를 재사용하지 마십시오.
- VB.NET에서 정적/공유 상태로 만들지 마십시오.
- 항상 생성, 열기(연결의 경우), 사용, 닫기 및 필요한 곳에 폐기(예: 방법)
- 를 사용하여 암시적으로 처리하고 닫습니다(연결의 경우).
이는 연결에만 해당되는 것이 아닙니다(가장 눈에 띄지만).구현하는 모든 객체는 (가장 단순하게) 배치되어야 하며, 더욱 더System.Data.SqlClient
네임스페이스입니다.
위의 모든 내용은 모든 개체를 캡슐화하고 재사용하는 사용자 지정 DB-Class에 반대합니다.그것이 제가 그것을 버리라고 댓글을 단 이유입니다.그것은 단지 문제의 근원일 뿐입니다.
편집: 가능한 구현 방법은 다음과 같습니다.retrievePromotion
filename:
public Promotion retrievePromotion(int promotionID)
{
Promotion promo = null;
var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MainConnStr"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
var queryString = "SELECT PromotionID, PromotionTitle, PromotionURL FROM Promotion WHERE PromotionID=@PromotionID";
using (var da = new SqlDataAdapter(queryString, connection))
{
// you could also use a SqlDataReader instead
// note that a DataTable does not need to be disposed since it does not implement IDisposable
var tblPromotion = new DataTable();
// avoid SQL-Injection
da.SelectCommand.Parameters.Add("@PromotionID", SqlDbType.Int);
da.SelectCommand.Parameters["@PromotionID"].Value = promotionID;
try
{
connection.Open(); // not necessarily needed in this case because DataAdapter.Fill does it otherwise
da.Fill(tblPromotion);
if (tblPromotion.Rows.Count != 0)
{
var promoRow = tblPromotion.Rows[0];
promo = new Promotion()
{
promotionID = promotionID,
promotionTitle = promoRow.Field<String>("PromotionTitle"),
promotionUrl = promoRow.Field<String>("PromotionURL")
};
}
}
catch (Exception ex)
{
// log this exception or throw it up the StackTrace
// we do not need a finally-block to close the connection since it will be closed implicitly in an using-statement
throw;
}
}
}
return promo;
}
저는 며칠 전에 이 오류를 발견했습니다.
저의 경우에는 싱글톤에서 트랜잭션을 사용하고 있었기 때문입니다.
.Net은 위에서 언급한 것처럼 Singleton과 잘 작동하지 않습니다.
제 해결책은 다음과 같습니다.
public class DbHelper : DbHelperCore
{
public DbHelper()
{
Connection = null;
Transaction = null;
}
public static DbHelper instance
{
get
{
if (HttpContext.Current is null)
return new DbHelper();
else if (HttpContext.Current.Items["dbh"] == null)
HttpContext.Current.Items["dbh"] = new DbHelper();
return (DbHelper)HttpContext.Current.Items["dbh"];
}
}
public override void BeginTransaction()
{
Connection = new SqlConnection(Entity.Connection.getCon);
if (Connection.State == System.Data.ConnectionState.Closed)
Connection.Open();
Transaction = Connection.BeginTransaction();
}
}
HttpContext를 사용했습니다.현재의.제 경우를 위한 항목.이 클래스 DbHelper 및 DbHelperCore는 나만의 클래스입니다.
언급URL : https://stackoverflow.com/questions/9705637/executereader-requires-an-open-and-available-connection-the-connections-curren
'programing' 카테고리의 다른 글
대상...'Pods/Pods.xccconfig'에 정의된 'OTHER_LDFLAGS' 빌드 설정을 재정의합니다. (0) | 2023.05.17 |
---|---|
MongoDB를 사용하여 최대 절전 모드로 전환 (0) | 2023.05.17 |
여러 필드에 대한 Node.js 및 Mongoose 정규식 쿼리 (0) | 2023.05.12 |
GitHub에서 분기된 repo 삭제 (0) | 2023.05.12 |
파이썬에서 16진수 문자열을 바이트로 변환하는 방법은 무엇입니까? (0) | 2023.05.12 |