모범 사례는 .NET 코드에서 IDBConnection 또는 연결 문자열/공장 공유를 다시 공유합니다.

StackOverflow https://stackoverflow.com/questions/414207

문제

.NET 애플리케이션의 데이터베이스에 대한 메인 연결 연결에 관한 최상의 사전이 무엇인지 궁금합니다 (ADO.NET이지만 모든 데이터 계층에 대해서는 연습이 동일해야한다고 생각합니다). 데이터베이스 연결을 생성하고 응용 프로그램 전반에 걸쳐 전파 해야하는 경우 연결 문자열/공장을 통과하고 필요할 때 연결 애드혹을 만드는 것이 좋습니다.

Perfomance hit은 풀링과 상당하지 않으며 깨진 연결에서 아주 쉽게 복구 할 수 있지만 (새로운 연결 만 생성 될 것입니다) 연결 객체는 상대적으로 비교적 높은 수준의 추상화와 새로운 연결을 만드는 것입니다. 모든 작업에 대해 (SQL 명령이 아니라 응용 프로그램 작업)는 추가로 복제 된 코드를 생성하며 시간/자원 낭비 (?)처럼 느껴집니다.

이 두 가지 사례에 대해 어떻게 생각하십니까, 그들의 단점/장점은 무엇이며 실제 응용 프로그램에서 어떤 접근법을 사용하고 있습니까?

감사

도움이 되었습니까?

해결책

나는 연결 객체를 전달해야한다는 것을 알았으므로 여러 비즈니스 객체가 단일 트랜잭션 내부의 데이터베이스에 자신을 저장할 수 있도록 할 수있었습니다.

각 비즈니스 객체가 데이터베이스에 자체 SQLConnection을 작성 해야하는 경우, 트랜잭션은 분산 트랜잭션으로 확대되어 피하고 싶었습니다.

객체를 저장하기 위해 SQLConnection 객체를 매개 변수로 전달하는 것을 좋아하지 않았으므로 SQLConnection 객체를 작성하고 SQLConnection 객체의 사용을 추적하고 사용하지 않을 때 SQLConnection 객체를 분리하는 ConnectionManager를 만들었습니다.

다음은 ConnectionManager의 예로서 코드입니다.

public class ConnectionManager: IDisposable
{
    private ConnectionManager instance;

    [ThreadStatic]
    private static object lockObject; 
    private static Object LockObject
    {
        get
        {
            if (lockObject == null)
                lockObject = new object();
            return lockObject;
        }
    }

    [ThreadStatic]
    private static Dictionary<string, ConnectionManager> managers;
    private static Dictionary<string, ConnectionManager> Managers
    {
        get
        {
            if (managers == null)
                managers = new Dictionary<string, ConnectionManager>();
            return managers;
        }
    }

    private SqlConnection connection = null;
    private int referenceCount;
    private string name;


    public static ConnectionManager GetManager(string connectionName)
    {
        lock (LockObject)
        {
            ConnectionManager mgr;
            if (Managers.ContainsKey(connectionName))
            {
                mgr = Managers[connectionName];
            }
            else
            {
                mgr = new ConnectionManager(connectionName);
                Managers.Add(connectionName, mgr);
            }

            mgr.AddRef();
            return mgr;
        }
    }

    private ConnectionManager(string connectionName)
    {
        name = connectionName;
        connection = new SqlConnection(GetConnectionString(connectionName));
        connection.Open();
    }

    private string GetConnectionString(string connectionName)
    {
        string conString = Configuration.ConnectionString;
        return conString; 
    }

    public SqlConnection Connection
    {
        get { return connection; }
    }

    private void AddRef()
    {
        referenceCount += 1;
    }

    private void DeRef()
    {
        lock (LockObject)
        {
            referenceCount -= 1;
            if (referenceCount == 0)
            {
                connection.Dispose();
                Managers.Remove(name);
            }
        }
    }

#region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            DeRef();
        }
    }

    ~ConnectionManager()
    {
        Dispose(false);
    }

#endregion

}

비즈니스 개체에서 사용하는 방법은 다음과 같습니다.

public void Save()
{   
    using (ConnectionManager mrg = ConnectionManager.GetManager("SQLConnectionString")
    {
        using (SQLCommand cmd = new SQLCommand)
        {
            cmd.connection = mgr.Connection
            // More ADO Code Here
        }

        _childObject.Save(); //this child object follows the same pattern with a using ConnectionManager.
    }
}

비즈니스 객체를 저장하고 모든 어린이는 동일한 연결 객체를 사용하여 저장됩니다. 범위가 원래 부모로부터 떨어지면 사용 명령문이 연결을 닫습니다.

이것은 CSLA 프레임 워크에서 Rocky Lhotka에서 배운 패턴입니다.

키이스

다른 팁

당신을 위해 할 수있는 수많은 도구가 있기 때문에이 문제를 직접 처리해서는 안됩니다.

당신이 정말로 직접하고 싶다면 작업 단위 연결/트랜잭션 라이프 사이클을 관리 할 수있는 패턴. 당신은 확실히 다른 장소에서 연결/닫히는 지저분한 물을 탐색하려고하지 않습니다.

구성 요소가 DB 연결을 직접 열기로 결정한 경우 연결 라이프 사이클이 너무 세밀하게 입자가되어 단일 사용자 작업을 위해 많은 개방/폐쇄 연결을 초래할 수 있습니다.

Ado.net SQL Server 제공자는 연결 풀링 자체를 수행합니다. 풀 크기를 제어 할 수 있습니다 MinPoolSize 그리고 MaxPoolSize 연결 문자열에서.

예에서 조심해야 할 것은 ASP.NET 앱은 스레드 스토리지를 사용해서는 안되며 스레드를 재사용 할 수 있고 모든 객체를 정리하지 않으면 연결이 매달려있는 것으로 끝납니다.

asp.net 앱에서 대신 httpcontext.items 컬렉션을 사용합니다. 당신은 idisposable을 구현하고 있지만, devs가 처분을 호출하거나 사용 블록에 배치하는 것을 잊어 버리는 시나리오를 보았습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top