n-tier Entity Framework 솔루션을 사용한 의존성 주입


12

현재 Entity Framework 5 (.net 4)를 데이터 액세스 전략으로 사용하는 n 계층 솔루션을 설계하고 있지만 의존성 주입을 통합하여 테스트 가능하고 유연하게 만드는 방법에 대해 우려하고 있습니다.

현재 솔루션 레이아웃은 다음과 같습니다 (내 솔루션은 Alcatraz라고 함).

Alcatraz.WebUI : 프론트 엔드 사용자 인터페이스 인 asp.net 웹 양식 프로젝트는 Alcatraz.BusinessAlcatraz.Data.Models 프로젝트를 참조합니다 .

Alcatraz.Business : 비즈니스 라이브러리를 포함하는 클래스 라이브러리 프로젝트, 프로젝트 Alcatraz.Data.Access , Alcatraz.Data.Models 참조

Alcatraz.Data.Access : 클래스 라이브러리 프로젝트, 주택 AlcatrazModel.edmxAlcatrazEntitiesDbContext, 참조하는 프로젝트 Alcatraz.Data.Models .

Alcatraz.Data.Models : 클래스 라이브러리 프로젝트로, 알카트라즈 모델에 대한 POCO를 포함하며 참조는 없습니다.

이 솔루션의 작동 방식에 대한 나의 비전은 웹 UI가 비즈니스 라이브러리 내에서 저장소를 인스턴스화하는 것이며,이 저장소는 (생성자가 아닌) 연결 문자열 ( AlcatrazEntities인스턴스 아님)의 종속성을 갖습니다 . web-ui는 데이터베이스 연결 문자열을 알고 있지만 엔터티 프레임 워크 연결 문자열 인 것은 아닙니다.

비즈니스 프로젝트에서 :

public class InmateRepository : IInmateRepository
{
    private string _connectionString;

    public InmateRepository(string connectionString)
    {
        if (connectionString == null)
        {
            throw new ArgumentNullException("connectionString");
        }

        EntityConnectionStringBuilder connectionBuilder = new EntityConnectionStringBuilder();

        connectionBuilder.Metadata = "res://*/AlcatrazModel.csdl|res://*/AlcatrazModel.ssdl|res://*/AlcatrazModel.msl";
        connectionBuilder.Provider = "System.Data.SqlClient";
        connectionBuilder.ProviderConnectionString = connectionString;

        _connectionString = connectionBuilder.ToString();
    }

    public IQueryable<Inmate> GetAllInmates()
    {
        AlcatrazEntities ents = new AlcatrazEntities(_connectionString);

        return ents.Inmates;
    }
}

웹 UI에서 :

IInmateRepository inmateRepo = new InmateRepository(@"data source=MATTHEW-PC\SQLEXPRESS;initial catalog=Alcatraz;integrated security=True;");

List<Inmate> deathRowInmates = inmateRepo.GetAllInmates().Where(i => i.OnDeathRow).ToList();

이 디자인에 대한 몇 가지 관련 질문이 있습니다.

  1. 이 디자인은 Entity Frameworks 기능 측면에서도 의미가 있습니까? 엔티티 프레임 워크가 이미 작업 단위 패턴을 사용한다고 들었습니다. 불필요하게 다른 추상 레이어를 추가하고 있습니까?

  2. 내 웹 UI가 Entity Framework와 직접 통신하기를 원치 않으며 (또는 그 문제를 참조하기 위해) 향후 동일한 비즈니스 계층을 사용하는 여러 프로젝트가있을 때 모든 데이터베이스 액세스가 비즈니스 계층을 통과하기를 원합니다. (웹 서비스, Windows 응용 프로그램 등) 하나의 중앙 영역에 비즈니스 논리를 가짐으로써 유지 관리 / 업데이트를 쉽게하고 싶습니다. 이것이 이것을 달성하는 적절한 방법입니까?

  3. 비즈니스 계층에 리포지토리가 포함되어야합니까, 아니면 액세스 계층 내에 포함되어야합니까? 그들이 어디에 있는지, 연결 문자열을 전달하는 것이 좋은 의존성을 가정합니까?

읽어 주셔서 감사합니다!

답변:


11

DI를하는 방식이 잘못되었습니다.

먼저 연결 문자열이 데이터 계층에 속합니다. 또는 web.config 파일에서.

다룰 다음 추상화는 연결 문자열이 아닌 DbContext입니다. 리포지토리는 연결 문자열에 대해 알아야합니다. 비즈니스 로직은 DbContext 등에 대해 알지 못합니다.

UI는 전혀 몰라 EF와 관련된 어떤 것도 인스턴스화하지 않습니다.

당신의 요점에 대한 구체적인 답변 :

  1. EF에 익숙해 질 때까지 추상화를 추가하지 마십시오. 이미 UoW, 쿼리, POCO 사용 등의 좋은 추상화를 추가합니다.

  2. DI가 작동하려면 필요한 모든 구성 요소를 참조하는 컴포지션 루트가 있습니다. 이것은 WebUI 프로젝트에 있거나 없을 수 있습니다. 그렇지 않은 경우 EF 또는 기타 데이터 관련 기술을 참조하지 않아야합니다.

  3. 여기서 멈춰 추상화에 추상화를 추가하지 마십시오. 직접적이고 '순진한'아키텍처로 시작하여 시간이 지남에 따라 개발하십시오.

추상화는 복잡성을 처리하는 도구입니다. 복잡성의 부재는 아직 추상화가 필요하지 않음을 의미합니다.


나는 당신이 말하는 것을 이해하기 위해 : 인터페이스 (비즈니스에 인터페이스가 있고 Alcatraz.Data.Access에 콘크리트가 있습니까?)는 DbContext의존성을 a 로 받아들 입니다. 비즈니스 클래스에는 저장소가 종속성으로 있습니다. 의존성 주입의 경우 수동 으로이 작업을 수행하고 있습니다 (그래서 진행 상황을 이해합니다). 연결 문자열을 설정하려는 이유 DbContext는 데이터베이스 샤딩을 사용하기 때문에 특정 경우 동일한 구조의 다른 데이터베이스에 연결하기 위해 엔티티 프레임 워크가 필요하기 때문입니다. 내가 당신을 제대로 이해합니까?
Matthew

제공 한 코드에서 DI를 전혀하지 않는 것 같습니다. DI의 주요 목표는 사용자와 코드가 종속성을 관리하지 못하게하는 것입니다. DI 컨테이너없이 수동으로 효과적으로 수행한다고 상상할 수 없습니다.
Boris Yankov

DI로 마음을 열어 두십시오. 나는 이미 재미를 위해 다른 포럼에서 똑같은 질문을하여 반대 답변을 얻었습니다. DI는 패턴이 아니라 아키텍처입니다. 목표에 따라 사용 여부를 결정할 수 있습니다. 나는 그것을 사용하지만 대부분의 사람들이 그것을 사용한다고 말한 이유는 아닙니다.
Bastien Vandamme

4

몇 가지 간단한 의견. 나는 개인적으로 연결 문자열을 전달하지 않을 것입니다. 내가 저장소를 위해 인터페이스를 만들고 시도하고 인터페이스를 전달하려고하는 것이 있다면? 리포지토리에 IOW 인터페이스를 구현하거나 노출 시키십시오.

이런 식으로 이벤트가 리포지토리를 구현하는 데이터베이스 일 필요는 없습니다. 그것들은 메모리 캐시에 있거나 또는 무엇이든 될 수 있습니다. 아마도 일종의 의존성 주입 프레임 워크를 사용하여 이러한 인스턴스를 인스턴스화 할 수 있습니까?

따라서 귀하의 몇 가지 질문에 대한 답변으로 :

  1. 네 괜찮아요
  2. 여전히 UI 참조로 EF 프로젝트와 EF 저장소 레이어가 구현하는 비즈니스 계층 참조 인터페이스를 갖습니다. 이렇게하면 다른 프로젝트에서 여전히 동일한 어셈블리를 사용할 수 있지만 원하는 경우 교체 할 수있는 유연성이 있습니까?
  3. 흠, 아마도 액세스 계층의 리포지토리이지만 비즈니스 계층에 노출 된 인터페이스 정의를 구현하고 있습니까?

이것들은 몇 가지 생각에 지나지 않습니다.


포인트 2에 대해, 내가 만들려고 한 목표는 ui 레이어 내에 CRUD를 직접 사용하지 않는 것입니다. 의미하는 바는 비즈니스 계층을 통해 관리되는 방식으로 CRUD 만 발생할 수 있기를 원한다는 것입니다.
Matthew
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.