2009-03-13 2 views
15

나는 이것을 수행하는 가장 깨끗한 방법을 찾으려고합니다.비즈니스 개체에 대한 데이터 액세스 계층에 가장 적합한 "패턴"

public class Customer 
{ 
    public int Id {get;set;} 
    public string name {get;set;} 
    public List<Email> emailCollection {get;set} 
    public Customer(int id) 
    { 
     this.emailCollection = getEmails(id); 
    } 
} 

그런 다음 내 이메일 객체가 아주 기본입니다 :

현재 전 고객 개체가 있습니다.

public class Email 
{ 
    private int index; 
    public string emailAddress{get;set;} 
    public int emailType{get;set;} 
    public Email(...){...} 
    public static List<Email> getEmails(int id) 
    { 
     return DataAccessLayer.getCustomerEmailsByID(id); 
    } 
} 

DataAccessLayer 현재 데이터베이스에 연결하고, 결과 집합을 반복하는 SqlDataReader 개체를 사용하여 새로운 이메일 객체를 생성하고 할 때 반환하는 목록에 추가합니다.

어디서 어떻게 개선 할 수 있습니까?

DataAccessLayer 대신 DataTable을 반환하고이를 전자 메일 개체로 남겨두면 분석 결과를 고객에게 반환 할 수 있습니까?

"Factory"는 아마도 잘못된 단어 일 것 같지만 DataAccessLayer에서 DataTable을 가져 와서 Email 객체에 List를 반환하는 다른 유형의 EmailFactory가 있어야합니까? 그런 종류의 소리가 중복되는 것 같아요.

내 Email.getEmails (id)를 정적 방법으로 사용하는 것이 합당한 방법입니까?

평소에 간단한 작업으로 가장 좋은 "패턴"을 찾아 적용하려고 시도해 보았습니다.

감사합니다.


는 후속

는 내 도메인/비즈니스 오브젝트가 기존 데이터베이스에서 ID로 고객 레코드를 추출하는 작업 예제를 만들었습니다. nhibernate의 xml 매핑 파일은 정말 멋지다. 튜토리얼을 따라 세션과 저장소 팩토리를 설정 한 후에 데이터베이스 레코드를 가져 오는 것은 꽤나 간단했습니다.

그러나 엄청난 성능 저하가 나타났습니다.

내 원본 메서드는 결과 집합을 내 도메인/비즈니스 개체로 구문 분석 한 DAL 개체에서 호출 한 DB의 저장 프로 시저로 구성됩니다.

나는 단일 고객 기록을 얻기 위해 30 밀리 잡기로 나의 원래 방법을 계시했다. 나는 같은 기록을 얻기 위해 3000ms를 복용하면서 nhibernate 방법을 기록했다.

내가 누락 된 항목이 있습니까? 아니면이 nhibernate 경로를 사용하여 오버 헤드가 많이 있습니까?

그렇지 않으면 나는 코드의 청결을 좋아한다 :

protected void Page_Load(object sender, EventArgs e) 
{ 
    ICustomerRepository repository = new CustomerRepository(); 
    Customer customer = repository.GetById(id); 
} 

public class CustomerRepository : ICustomerRepository 
     { 
      public Customer GetById(string Id) 
      { 
       using (ISession session = NHibernateHelper.OpenSession()) 
       { 
        Customer customer = session 
             .CreateCriteria(typeof(Customer)) 
             .Add(Restrictions.Eq("ID", Id)) 
             .UniqueResult<Customer>(); 
        return customer; 
       } 
      } 
     } 

example I followed 제가이 오버 헤드를 받고 있어요 왜 아마도 그건, 세션을 관리하는 데 도움이 헬퍼 클래스를 생성했다?

public class NHibernateHelper 
    { 
     private static ISessionFactory _sessionFactory; 
     private static ISessionFactory SessionFactory 
     { 
      get 
      { 
       if (_sessionFactory == null) 
       { 
        Configuration cfg = new Configuration(); 
        cfg.Configure(); 
        cfg.AddAssembly(typeof(Customer).Assembly); 
        _sessionFactory = cfg.BuildSessionFactory(); 
       } 
       return _sessionFactory; 
      } 

     } 

     public static ISession OpenSession() 
     { 
      return SessionFactory.OpenSession(); 
     } 
    } 

내가 작업하고있는 응용 프로그램을 사용하면 속도가 핵심입니다. 궁극적으로 많은 양의 데이터가 웹 앱과 데이터베이스간에 전달됩니다. 3 초가 아니라 고객 레코드를 끌어 올리기 위해 1/3 초의 에이전트가 필요하다면 큰 타격을 입을 것입니다.하지만 내가 이상한 일을하고 있는데 이것은 초기 설치 비용이 한 번만 들었다면 DB의 저장 프로 시저를 실행하는 것만 큼 성능이 좋았다면 가치가있을 것입니다.

아직 제안이 없습니다!


업데이트 됨.

나는 내 ORM/NHibernate 경로를 폐기하고 있습니다. 나는 그것을 사용하는 것을 정당화하기에는 성능이 너무 느리다는 것을 발견했다. 기본 고객 쿼리는 우리 환경에 너무 오래 걸립니다. 1 초 미만의 응답에 비해 3 초가 너무 많습니다.

우리가 느린 쿼리를 원한다면 우리는 현재의 구현을 유지할 것입니다. 그것을 재 작성하는 아이디어는 시간을 크게 늘리는 것이 었습니다.

그러나 지난 주 NHibernate와 함께 해본 결과 훌륭한 도구입니다! 이 프로젝트에 대한 나의 요구에 꼭 맞지 않습니다.

+0

Barry- 그래, 지금 당장 위대한 일을하고 있습니다. 내가 생각할 수있는 것은 DataAccessLayer가 DataTable을 반환하도록함으로써 데이터 액세스 레이어 대신 비즈니스 레이어 (즉, 이메일 개체)에서 유효성 검사를 수행 할 수 있도록하는 것입니다. –

+1

게시 한 예는 고전적인 "빈혈 도메인 모델"입니다. 귀하의 예를 기반으로하면 비즈니스 객체조차 필요하지 않습니다. 비즈니스 객체는 비즈니스 로직을 유지해야하며, 비즈니스 로직은 보유하지 않아야합니다. –

답변

6

구성이 지금 작동하는 경우 왜 그걸로 엉망이됩니까? 코드와 관련하여 특정 요구 사항이나 문제를 식별하는 것처럼 들리는 것은 아닙니다.

많은 OO 유형들이 모여서 정확한 리팩토링을 제안하여 올바른 책임과 역할을 존중할 수 있으며 누군가 디자인 패턴 2 또는 3 가지로 구h 주걱을 시도 할 수도 있습니다. 그러나 당신이 지금 가지고있는 코드는 간단하고 아무런 이슈도없는 것처럼 들린다. 나는 그것을 떠날 것이라고 말하고 싶다.

+0

나 자신을 OO라고 생각하지만, 나는 진심으로 동의한다. 현재의 솔루션은 너무 단순해서 이해할 수도 있습니다. 이것은 확실히 좋은 품질입니다! – Treb

+2

하나의 제안은 비즈니스 개체에 "비즈니스"동작을 추가하는 것입니다. 비즈니스 개체가 위에서 올바르게 사용되지 않는 것 같습니다. –

5

기본적으로 NHibernate가 수행하지만 수동으로 수행하는 DAL 계층을 구현했습니다. NHibernate가하는 일은 도메인 객체 (모든 필드가 가상으로 표시되어야 함)를 상속받는 Proxy 클래스를 만드는 것입니다. 모든 데이터 액세스 코드는 속성 오버라이드에 사용됩니다. 실제로는 매우 우아합니다.

저는 리포지토리가 간단한 속성 자체를 채우고 지연로드 용으로 프록시 만 사용하도록함으로써 다소 단순화했습니다. 내가 결국은이 같은 클래스의 집합입니다 :

public class Product { 
    public int Id {get; set;} 
    public int CustomerId { get; set;} 
    public virtual Customer Customer { get; set;} 
} 
public class ProductLazyLoadProxy { 
    ICustomerRepository _customerRepository; 
    public ProductLazyLoadProxy(ICustomerRepository customerRepository) { 
    _customerRepository = customerRepository; 
    } 
    public override Customer { 
    get { 
     if(base.Customer == null) 
     Customer = _customerRepository.Get(CustomerId); 
     return base.Customer 
    } 
    set { base.Customer = value; } 
    } 
} 
public class ProductRepository : IProductRepository { 
    public Product Get(int id) { 
    var dr = GetDataReaderForId(id); 
    return new ProductLazyLoadProxy() { 
     Id = Convert.ToInt(dr["id"]), 
     CustomerId = Convert.ToInt(dr["customer_id"]), 
    } 
    } 
} 

그러나 20이의를 작성 후, 난 그냥 요즘 장애물이 그 어느 때보 다 낮은 구성에 대한 질의 및 FluentNHibernate에 대한 Linq2NHibernate으로, NHibernate에를 포기하고 배웠습니다.

2

이것은 너무 급진적 일 수 있으며 질문을 실제로 해결하지는 않지만 데이터 계층을 완전히 폐기하고 ORM을 선택하는 방법은 무엇입니까? DAL에서 1 주일 정도 소요되는 많은 코드 중복을 줄일 수 있습니다.

그렇다면 사용중인 패턴은 일종의 저장소 패턴과 유사합니다. 귀하의 옵션은 다음과 같습니다

    이메일 클래스의 서비스 개체 (예 : EmailService)가 생성자 또는 속성에서 인스턴스화되었습니다. 과 같은 예를 통해 액세스 email.Service.GetById (ID)
  • 이메일에 고정하는 방법과 유사한 방법 Email.GetById
  • 기본적 외관 클래스 완전히 분리 정적 클래스 (ID) 등 예를 들어, EmailManager.GetById (int)와 같은 정적 메소드가있는 EmailManager
  • email.Save() 및 email과 같이 인스턴스를 처리하는 ActiveRecord 패턴.GetById()
2

응용 프로그램의 도메인 논리 설정이 transaction scripts 일 가능성이 높습니다. 트랜잭션 스크립트를 사용하는 .NET 구현의 경우 Martin Fowler는 table data gateway 패턴의 사용을 권장합니다. .NET은이 패턴을 잘 지원합니다. 테이블 데이터 게이트웨이 패턴이 record set과 비슷하기 때문입니다. Microsoft는 해당 DataSet 유형 클래스를 구현합니다.

Visual Studio 환경 내의 다양한 도구를 사용하면 생산성이 향상됩니다. DataSets를 다양한 컨트롤 (예 : DataGridView)에 쉽게 데이터 바인딩 할 수 있으므로 데이터 기반 응용 프로그램에 적합합니다.

비즈니스 논리가 몇 가지 유효성 검사보다 복잡한 경우 domain model이 좋은 옵션이됩니다. 도메인 모델에는 완전히 다른 데이터 액세스 요구 사항이 있습니다.

관련 문제