2017-03-21 2 views
4

응용 프로그램 시작 중에 SqlConnection 개체를 인스턴스화하기 위해 .NET 핵심 종속성 주입을 사용하고 있습니다.이 개체를 저장소에 삽입 할 계획입니다. 이 SqlConnection은 내 저장소 구현 내에서 데이터베이스에서 데이터를 읽거나 쓰려면 Dapper가 사용합니다. Dapper로 async 통화를 사용하겠습니다.Dapper with .NET 코어 주입 SqlConnection 수명/범위

질문은 : SqlConnection을 일시적으로 또는 싱글 톤으로 주입해야합니까? 실제로 Dapper가 내부적으로 격리 컨테이너를 구현하지 않고 Dapper가 내부적으로 사용하는 범위 내에서 내 Singleton의 범위가 여전히 랩핑되지 않는 한, async을 사용하려고한다는 사실을 고려할 때 일시적으로 사용하는 것이 좋습니다.

Dapper로 작업 할 때 SqlConnection 개체의 수명과 관련하여 권장 사항이나 모범 사례가 있습니까? 내가 누락 될 수있는주의 사항이 있습니까?

미리 감사드립니다.

답변

3

싱글 톤으로 SQL 연결을 제공하는 경우 MARS를 사용하도록 설정하지 않으면 여러 요청을 동시에 처리 할 수 ​​없으며 제한도 있습니다. 가장 좋은 방법은 일시적인 SQL 연결을 사용하고 적절히 처리되도록하는 것입니다.

제 신청서에 IDbConnectionFactoryusing 내부에 연결을 생성하는 데 사용되는 저장소에 전달합니다. 이 경우 저장소 자체는 힙에 대한 할당을 줄이기 위해 싱글 톤이 될 수 있습니다.

+0

나는 공장 접근 방식을 좋아하지만 어떻게 하나는 하나의 응용 프로그램에 대해 여러 데이터 소스의 (데이터베이스)와 함께 시나리오를 처리 할 것인가? 데이터베이스 당 자식'ISomeDbConnectionFactory'을 생성하고 추가 매개 변수를 팩토리에 전달하여 어떤 연결을 생성해야하는지 결정하십시오. 아니면 더 우아한 뭔가? –

+1

동일한 저장소가 단일 데이터 소스에 대한 연결을 사용한다고 가정합니다. 이 경우 데이터 소스 특정 연결 팩토리의 접근 방식을 사용합니다. 팩토리의 인터페이스는 동일 할 수 있으며, DB 전용 구현 일 수 있습니다. –

+0

MARS를 사용하는 경우에도 동일한 'SqlConnection'을 사용하여 여러 동시 요청을 처리 할 수 ​​없습니다. [MSDN] (https://msdn.microsoft.com/en-us/library/h32h3abf (v = vs.110) .aspx)에 따르면 : "MARS 작업은 스레드로부터 안전하지 않습니다". – Steven

3

@Andrii Litvinov와 답변 및 의견에 동의합니다.

이 경우에는 데이터 소스 관련 연결 팩토리 접근 방식을 사용합니다.

동일한 접근 방식으로, 나는 다른 방법을 언급하고있다. - UnitOfWork.

DalSessionUnitOfWork부터 this 대답을 참조하십시오. 이것은 연결을 처리합니다.
BaseDal에서 this 대답을 참조하십시오. 이것은 Repository (실제로는 BaseRepository)의 구현입니다.

  • UnitOfWork은 일시적으로 주입된다.
  • 각 데이터 소스에 대해 별도의 DalSession을 생성하면 여러 데이터 소스를 처리 할 수 ​​있습니다.
  • UnitOfWorkBaseDal에 주입된다.

는 SqlConnection 개체의 수명 단정 한 작업에 대한이 권장 사항/모범 사례인가?

대부분의 개발자가 동의하는 한 가지는 가능한 한 짧은 수명을 가져야한다는 것입니다. 여기에는 두 가지 접근 방식이 있습니다.

  1. 조치 당 연결.
    이것은 코스의 최단 수명입니다. 각 작업마다 using 블록에 연결을 묶습니다.이것은 작업을 그룹화하지 않는 한 좋은 접근 방법입니다. 액션을 그룹화 할 때도 대부분의 경우 트랜잭션을 사용할 수 있습니다.
    여러 클래스/메서드에서 작업을 그룹화하려는 경우 문제가 발생합니다. 여기서 using 블록을 사용할 수 없습니다. 아래는 UnitOfWork의 해결책입니다.
  2. 단위 작업 당 연결.
    작업 단위를 정의하십시오. 이것은 응용 프로그램마다 다릅니다. 웹 응용 프로그램에서 "요청 당 연결"방식이 널리 사용됩니다.
    일반적으로 우리가 전체적으로 수행하고자하는 (대부분의 경우) 그룹의 동작이 있기 때문에 이것은 더 의미가 있습니다. 이것은 위의 두 링크에서 설명합니다.
    이 접근법의 또 다른 이점은 응용 프로그램 (DAL을 사용하는)이 연결을 사용하는 방법을보다 잘 제어 할 수 있다는 것입니다. 그리고 내 이해에서 응용 프로그램 연결을 사용해야하는 방법을 DAL보다 잘 알고 있습니다.
1

위대한 질문과 이미 두 가지 큰 답변. 처음에는 당황스럽고 다음과 같은 해결책으로 관리자에게 저장소를 캡슐화하는 문제를 해결했습니다. 관리자는 연결 문자열을 추출하여 리포지토리에 주입해야합니다.

모의 콘솔 앱에서 말하는 리포지토리를 개별적으로 테스트하는 방법을 찾았습니다. 더 큰 규모의 여러 프로젝트에서이 패턴을 따르는 것이 좋습니다. 비록 필자가 테스트, 의존성 주입, 또는 무엇인가에 대한 전문가는 아니지만 정말로 그렇습니다!

나 자신에게 묻는 왼쪽 질문은 DbService가 싱글 톤인지 여부입니다. 나의 근거는 DbService에 캡슐화 된 다양한 저장소를 끊임없이 생성하고 파괴하는 것이별로 중요하지 않았기 때문이며, 그들은 모두 무국적이기 때문에 "살아야"하는 데 많은 어려움을 겪지 않았습니다. 이것은 완전히 무효 논리가 될 수 있지만.

편집 :

/* 
* Db Service 
*/ 
public interface IDbService 
{ 
    ISomeRepo SomeRepo { get; } 
} 

public class DbService : IDbService 
{ 
    readonly string connStr; 
    ISomeRepo someRepo; 

    public DbService(string connStr) 
    { 
     this.connStr = connStr; 
    } 

    public ISomeRepo SomeRepo 
    { 
     get 
     { 
      if (someRepo == null) 
      { 
       someRepo = new SomeRepo(this.connStr); 
      } 

      return someRepo; 
     } 
    } 
} 

샘플 저장소가 구성 될 것이다 : 당신은 다음과 같은 준비가 만든 솔루션 저장소 관리자의 구조 GitHub

내 말끔 저장소 구현을 확인하려는해야 다음과 같습니다 :

배선 모두 최대 : 그것을 사용

/* 
* Startup.cs 
*/ 
public IConfigurationRoot Configuration { get; } 

public void ConfigureServices(IServiceCollection services) 
{ 
    //...rest of services 

    services.AddSingleton<IDbService, DbService>(); 

    //...rest of services 
} 

마지막을 :

public SomeController : Controller 
{ 
    IDbService dbService; 

    public SomeController(IDbService dbService) 
    { 
     this.dbService = dbService; 
    } 

    public IActionResult Index() 
    { 
     return View(dbService.SomeRepo.List()); 
    } 
}