2010-05-07 4 views
14

웹 응용 프로그램을 구축 한 경험으로 항상 n 계층 접근 방식을 사용했습니다. db에서 데이터를 가져 와서 개체를 채우는 DAL과 DAL에서 개체를 가져 와서 비즈니스 로직을 수행하는 BLL 및 BLL의 표시 데이터를 가져 오는 웹 사이트. 최근에 LINQ를 배우기 시작했으며, 대부분의 예제에서는 웹 응용 프로그램 코드 숨김에서 발생하는 쿼리를 보여줍니다 (단순한 예제 만 보았을 가능성이 있습니다). n-tier 아키텍처에서 이것은 항상 큰 no-no로 간주되었습니다.
저는 새로운 웹 애플리케이션을 설계하는 방법에 대해 확신이 없습니다. 나는 VS2008에서 dbml과 객체 관계를 만들기 위해 서버 탐색기와 dbml 디자이너를 사용 해왔다. 웹 사이트 등 다음 LINQ 쿼리를 할 것 BLL, 내 메소드를 호출해야하는 경우 DBML이는 DAL 층 간주 될 수 있다면 그것은 나에게 조금 불분명 보인다
일반적인 아키텍처 모범 사례, 또는에 접근 무엇 LINQ to SQL을 사용하여 웹 응용 프로그램 솔루션을 만들 수 있습니까? 당신이 DAL 및 BLL 사이에 분리하려는 경우LINQ to SQL 웹 응용 프로그램 모범 사례

답변

16

나는 당신이 참으로 지나치게 단순화 된 예를 본 적이 두려워. LINQ to SQL (System.Data.Linq)은 DAL 계층입니다. L2S에서 생성하는 클래스는 귀하의 도메인입니다 (단, Domain-Driven Design과 혼동하지 마십시오). 그 위에 비즈니스 계층을 작성할 수 있습니다.

나는 항상 프리젠 테이션 계층 (웹 응용 프로그램)에 DataContext를 SQL 위해 LINQ를 유출 방지하려고합니다. 따라서 DataContext을 만들거나 커밋 할 수 없습니다. 또한 IQueryable<T> 개체를 프레젠테이션 계층에 반환해야합니다. IMO 비즈니스 계층은 DataContext (작업 단위)의 수명과 SQL 쿼리의 모양을 완전히 제어해야합니다.

그러나 몇 가지 맛이 있습니다. 어떤 사람들은 이러한 제약을 완화하기 위해 천막을 젓는다. 다른 사람들은 훨씬 더 많이 나아 간다. 그것은 자신의 취향과 응용 프로그램의 크기에 따라 다릅니다. 애플리케이션이 클수록 더 많은 추상화 레이어를 추가 할 수 있습니다.

IQueryable의를 허용하지 및 기타 데이터가 비즈니스 계층을 떠나는 물건을 관련, 당신은 몇 가지 흥미로운 도전을 필요하게 될 겁니다. 예를 들어, 프리젠 테이션 계층은 결과를 정렬하는 방법을 비즈니스 계층에 지시해야합니다. 프리젠 테이션 계층이 결과 자체를 정렬하도록 할 수는 있지만, 이는 프레젠테이션 계층에서 데이터베이스와 모든 페이지의 데이터를 가져와야하는 경우, 매우 나쁜 성능의 시스템으로 이어질 수 있습니다. 이 문제에 대한 해결책은 여러 가지가 있습니다. 모든 경우에 비즈니스 계층에 결과를 정렬하는 방법을 알릴 필요가 있습니다. 솔루션은 LINQ dynamic sort을 검색 할 때 SO에서 여기에서 찾을 수 있습니다. 나는 그러한 해결책을 직접 작성했다. here. 가져올 것이다 당신의 BL을 떠나는 IQueryable의를 허용하지

또 다른 문제는 도메인 객체가 자주 BL을 떠날 수 있다는 것입니다. 대부분의 LINQ to SQL 도메인 개체에는 지연로드 속성 (예 : 다른 도메인 개체에 대한 모음)이 포함됩니다. 그러나 DataContext이 비즈니스 계층을 제어하는 ​​경우 결과가 프레젠테이션 계층에 반환되기 전에 폐기됩니다. 프레젠테이션이 지연로드 된 속성에 액세스 할 때 DataContext이 이미 삭제되었으므로 예외가 발생합니다. DataContext을 비즈니스 계층에 배치하면이 동작은 물론 '의도적으로'이루어집니다.프리젠 테이션 레이어가 게으른로드 속성을 갖도록 허용하면 BL이 데이터베이스로 전송되는 쿼리를 제어하지 못하게되어 성능을 제어 할 수 없게됩니다.

이 문제를 해결하려면 BL에서 프레젠테이션 계층에 DTO (데이터 전송 개체)를 반환해야합니다. DTO는 데이터 만 포함하고 내부가 DataContext이고 지연된 속성은 포함되지 않습니다. DTO는 실제 요청에 맞게 특별히 포맷 될 수 있습니다. 물론 DTO로 인해 코딩 오버 헤드가 발생하기 때문에 시스템의 크기와 성능 요구가이를 정당화해야합니다. 나 자신을 더 쉽게 만들기 위해서, 나는 정적 인 투사 방법을 DTO에 두는 경향이있다. 이 방법은 separation of concerns 원칙을 따르지 않지만 아주 실용적인 해결책이 될 것입니다. 이 CustomerDTO에서 예를 들어 봐 :

public class CustomerDTO 
{ 
    public int CustomerId { get; set; } 
    public string Name { get; set; } 
    // City is flatterned from Address.City. 
    public string City { get; set; } 

    internal static IQueryable<CustomerDTO> AsDTO(IQueryable<Customer> customers) 
    { 
     return 
      from customer in customers 
      select new CustomerDTO() 
      { 
       CustomerId = customer.Id, 
       Name = customer.Name, 
       City = customer.Address.City 
      }; 
    } 
} 

이 DTO는 CustomerDTO DTO들의 컬렉션에 Customer 도메인 개체의 컬렉션을 변환 할 수있는 내부 AsDTO 방법을 정의합니다. 이것은 도메인 객체를 DTO로 변환하는 것을 훨씬 쉽게 만든다. 이 BL 방법에서, 예를 들어 봐 :

public static CustomerDTO[] GetCustomersByCountry(string country) 
{ 
    using (var db = ContextFactory.CreateContext()) 
    { 
     IQueryable<Customer> customers = 
      (from customer in db.Customers 
      where customer.Address.Country == country 
      orderby customer.Name, customer.Id); 

     return CustomerDTO.AsDTO(customers).ToArray(); 
    } 
} 

이 방법의 좋은 점은 당신이 SQL 쿼리를 볼 때, 당신이 볼 수 있다는 것입니다 만 고객 ID, 이름 및 주소 테이블의 도시 것 데이터베이스에서 검색 할 수 있습니다. AsDTO 메서드는 IQueryable을 다른 것으로 변환하기 때문에 LINQ to SQL에서 데이터베이스의 전체 작업을 수행 할 수 있습니다.

나는 이것이 당신이 할 수있는 것에 대한 아이디어를 줄 수 있기를 바랍니다. 물론, 이것은 주제에 대한 나의 견해와 내가 상황에서 실제적으로 발견 한 것들이다.

+0

철저한 답변을 보내 주셔서 감사합니다. 나는 프리젠 테이션 레이어에서 데이터 접근을하는 것을 싫어한다. 나는 현재 데이터 정렬에서 대부분의 정렬 작업을하는 경향이 있으므로 문제가되지는 않습니다. 나는 전에 DTO에 대해 들어 보지 못했고, 더 깊이 들여다 볼 수있는 것처럼 들린다. – derek

+0

DTO는 종종 오버 헤드가 많은 것으로 간주됩니다. 특히 유선을 통해 데이터를 전송할 때 유용합니다 (예 : WCF 또는 ASMX 웹 서비스가있는 경우). 예를 들어, Dino Esposito의 "Microsoft .NET : 엔터프라이즈 용 응용 프로그램 설계"를 읽으면 동일한 AppDomain의 계층간에 개체를 전송할 때 Dino가 일반적으로 오버 헤드가 많이 발생한다고 생각하는 것을 알 수 있습니다. 그는 이것에 대해 옳았는데 여전히 특정 시나리오에서 유용하다는 것을 알았고 기술이 향상 될 때 오버 헤드가 작아지는 것을 볼 수 있습니다 ... – Steven

+0

예를 들어 자동 속성과 같은 새로운 C# 언어 구문을 사용하면 DTO 및 리 팩터와 같은 리펙토링 도구! Pro는 LINQ 쿼리 내부의 익명 형식 정의에서 DTO를 자동으로 생성 할 수 있습니다. – Steven

4

는 SQL에 LINQ는 DAL 구현의 DB 접근이다. 복잡하지 않은 웹 응용 프로그램을 사용하는 경우 (그리고 DB 백엔드를 절대로 전환하지 않으려는 경우) 명시적인 DAL/BLL 없이도 벗어나 코드의 모든 것을 수행 할 수 있습니다. LINQ to SQL은 읽기 전용 연산에 적합하지만 쓰기 연산을 구현하는 데는 약간의 작업이 필요합니다.

관련 문제