Close 메서드를 명시 적으로 호출하거나 Using 문에 연결을 넣으면 쿼리를 닫아야합니까? 연결을 열어두면 연결 재사용이 가능하고 이후의 쿼리에서 SQL 성능이 향상됩니까?Dapper를 사용할 때 연결 닫기
답변
Dapper의 최신 버전을 사용하고 있다고 가정합니다.
완전 직접 관리 :
이 말끔으로 연결을 관리하는 방법은 두 가지가 여기 , 당신은 개폐 연결을위한 완전히 책임이 있습니다. 이는 ADO.NET으로 작업하는 동안 연결을 처리하는 것과 같습니다.
단정 그것을 관리 할 수 있도록 허용 : 단정 자동으로 (이 개설되지 않은 경우) 연결을 열고 (이 말끔 열 경우) 당신을 위해 그것을 닫습니다. 이것은
DataAdapter.Fill()
메소드와 유사합니다.개인적으로이 방법을 권장하지 않습니다.이것은 매번 적용되지 않을 수도 있습니다. 다음은 마크 Gravell이 응답에 대한 comment 중 하나에 말씀입니다 : https://stackoverflow.com/a/12629170/5779732
아니라, 폐쇄/기술적 오픈 배치 다릅니다. 개개인의 전화를 열거 나 닫을 예정이라면, 더할 나위없이 할 수 있습니다. 넓은 입도 (예 : 요청 당)로 열거 나 닫는 경우, 코드가이를 수행하고 dapper에 열린 연결을 전달하는 것이 좋습니다.
물론, 단일 연결에서 여러 쿼리를 호출 할 수 있습니다. 그러나 리소스 누출을 방지하려면 Close()
, Dispose()
메서드를 호출하거나 using
블록에 포함하여 연결을 닫아야합니다. 연결을 닫으면 연결 풀로 반환됩니다. 연결 풀이 포함되면 새로운 연결 비용보다 성능이 향상됩니다.
연결을 처리하는 것 외에도 트랜잭션을 관리하기 위해 UnitOfWork를 구현하는 것이 좋습니다. GitHub의 우수 샘플 this을 참조하십시오.
다음 소스 코드가 도움이됩니다. 이것은 내 필요를 위해 작성된 것입니다. 그래서 그것은 당신을 위해 일하지 않을 수도 있습니다.
public sealed class DalSession : IDisposable
{
public DalSession()
{
_connection = new OleDbConnection(DalCommon.ConnectionString);
_connection.Open();
_unitOfWork = new UnitOfWork(_connection);
}
IDbConnection _connection = null;
UnitOfWork _unitOfWork = null;
public UnitOfWork UnitOfWork
{
get { return _unitOfWork; }
}
public void Dispose()
{
_unitOfWork.Dispose();
_connection.Dispose();
}
}
public sealed class UnitOfWork : IUnitOfWork
{
internal UnitOfWork(IDbConnection connection)
{
_id = Guid.NewGuid();
_connection = connection;
}
IDbConnection _connection = null;
IDbTransaction _transaction = null;
Guid _id = Guid.Empty;
IDbConnection IUnitOfWork.Connection
{
get { return _connection; }
}
IDbTransaction IUnitOfWork.Transaction
{
get { return _transaction; }
}
Guid IUnitOfWork.Id
{
get { return _id; }
}
public void Begin()
{
_transaction = _connection.BeginTransaction();
}
public void Commit()
{
_transaction.Commit();
Dispose();
}
public void Rollback()
{
_transaction.Rollback();
Dispose();
}
public void Dispose()
{
if(_transaction != null)
_transaction.Dispose();
_transaction = null;
}
}
interface IUnitOfWork : IDisposable
{
Guid Id { get; }
IDbConnection Connection { get; }
IDbTransaction Transaction { get; }
void Begin();
void Commit();
void Rollback();
}
이제 리포지토리는이 UnitOfWork를 어떤 방식 으로든 받아 들여야합니다. 저는 Constructor로 Dependency Injection을 선택합니다.
public sealed class MyRepository
{
public MyRepository(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
IUnitOfWork unitOfWork = null;
//You also need to handle other parameters like 'sql', 'param' ect. This is out of scope of this answer.
public MyPoco Get()
{
return unitOfWork.Connection.Query(sql, param, unitOfWork.Transaction, .......);
}
public void Insert(MyPoco poco)
{
return unitOfWork.Connection.Execute(sql, param, unitOfWork.Transaction, .........);
}
}
그리고는 당신은 다음과 같이 호출 : 트랜잭션과
:
using(DalSession dalSession = new DalSession())
{
UnitOfWork unitOfWork = dalSession.UnitOfWork;
unitOfWork.Begin();
try
{
//Your database code here
MyRepository myRepository = new MyRepository(unitOfWork);
myRepository.Insert(myPoco);
//You may create other repositories in similar way in same scope of UoW.
unitOfWork.Commit();
}
catch
{
unitOfWork.Rollback();
throw;
}
}
거래하지 않고 :
using(DalSession dalSession = new DalSession())
{
//Your database code here
MyRepository myRepository = new MyRepository(dalSession.UnitOfWork);//UoW have no effect here as Begin() is not called.
myRepository.Insert(myPoco);
}
이 방법 대신 직접 전화의 연결을 노출시키는 코드를 사용하면 한 위치에서 제어 할 수 있습니다.
위 코드의 저장소에 대한 자세한 내용은 here을 참조하십시오.
UnitOfWork
은 트랜잭션보다 more입니다. 이 코드는 트랜잭션 만 처리합니다. 추가 역할을 포함하도록이 코드를 확장 할 수 있습니다.
두 번째 의견에 대해서는 완전히 동의 할 수 없습니다. 때로는 연결을 관리하기 위해 dapper를 사용하는 것이 더 나은 선택입니다. https://stackoverflow.com/a/12629170/1262198에서 Marc Gravell의 말을 인용하고 싶습니다. "기술적으로 열린 상태/닫히는 상태와 폐기 상태가 다릅니다. 개별 통화를 시작하거나 닫을 경우에만 만약 당신이 (예를 들어 요청 당 더 넓은 범위로) 열거 나 닫는다면, 당신의 코드가 그것을 수행하고 dapper에 열린 연결을 전달하는 것이 더 좋을 것입니다. " – Arvand
@Arvand : 동의하십시오. 내 대답을 바로 잡았어. 나는 이것이 매번 적용될 수 없다는 것을 의미합니다. –