2009-09-02 4 views
1

L2E를 사용하여 데이터 모델의 개체에 동작을 추가 할 때 가장 좋은 방법은 무엇입니까?LINQ to Entities 모델에 동작 추가

  • 당신은 단지 데이터를 필요로하는 동작을 구현하는 래퍼 클래스를 사용하면

    using (var dbh = new ffEntities()) 
        { 
         var query = from feed in dbh.feeds select 
            new FFFeed(feed.name, new Uri(feed.uri), feed.refresh); 
         return query.ToList(); 
        } 
        //Later in a separate place, not even in the same class 
        foreach (FFeed feed in feedList) { feed.doX(); } 
    
  • 직접 데이터 모델 인스턴스를 사용하고 그 인스턴스를 IEnumerable에서 작동하는 방법이 필요 갖는

    using (var dbh = new ffEntities()) 
        { 
         var query = from feed in dbh.feeds select feed; 
         return query.ToList(); 
        } 
        //Later in a separate place, not even in the same class 
        foreach (feeds feed in feedList) { doX(feed); } 
    
  • 데이터 모델 클래스의 확장 메서드를 사용하므로 래퍼에 추가 메서드가 있어야합니다.

    public static class dataModelExtensions { 
         public static void doX(this feeds source) { 
          //do X 
         } 
        } 
        //Later in a separate place, not even in the same class 
        foreach (feeds feed in feedList) { feed.doX(); } 
    

최고의 어느 하나? 나는 CRUD 기능을 방해하지 않는 깨끗한 방법으로 마지막 접근법을 선호하는 경향이 있습니다. (직접 삽입/업데이트/삭제하기 위해 사용할 수 있습니다. 다시 포장 할 필요는 없습니다.)하지만 내가 가진 안식처가 있는지 궁금합니다. 알았어.

네 번째 방법이 있습니까? 나는 LINQ의 철학을 이해하는데 실패한다. 특히 LINQ to Entities에 관한 것이다.

답변

1

엔티티 클래스는 알고있는 부분 클래스이므로 partial 키워드를 사용하여 직접 확장 한 다른 파일을 추가 할 수 있습니다.

그렇지 않으면 대개 래퍼 클래스, 즉 내 ViewModel (MVVM이있는 WPF를 사용하고 있습니다)이 있습니다. 또한 필자는 ViewModel에 특정 쿼리 필터를 추가하는 데 사용되는 유창한 인터페이스가있는 일반 도우미 클래스를 사용합니다.

1

실연을 엔티티 유형에 넣는 것은 실수라고 생각합니다.

엔티티 프레임 워크는 엔티티 데이터 모델을 기반으로하며 아키텍처 중 하나가 ".NET의 개체 데이터 모델과 매우 유사하게 동작"을 제공한다고 설명했습니다. 달리 말하면, 엔티티 모델은 관계형 데이터를 오브젝트 공간에 맵핑하도록 설계되었지만 메소드로 확장해서는 안됩니다. 비즈니스 유형에 대한 메소드를 저장하십시오.

다른 ORM과 달리, 블랙 박스에서 나오는 개체 유형에 구애받지 않습니다. LINQ가있는 엔티티 유형과 모양이 다른 경우에도 거의 모든 유형의 LINQ를 투영 할 수 있습니다. 비즈니스 코드, 데이터 전송 또는 프리젠 테이션 모델이 아닌 매핑에만 엔티티 유형을 사용하십시오.

코드가 생성 될 때 엔티티 유형이 부분 선언됩니다. 이로 인해 일부 개발자는 비즈니스 유형으로 확장하려고 시도합니다. 이것은 실수입니다. 사실 엔티티 유형을 확장하는 것이 거의 불가능합니다. 엔티티 모델에서 생성 된 속성은 LINQ to Entities에서 쿼리 할 수 ​​있습니다. 부분 클래스에 추가하는 속성 또는 메서드는 쿼리에 포함될 수 없습니다.

public Decimal CalculateEarnings(Guid id) 
{ 
    var timeRecord = (from tr in Context.TimeRecords 
         .Include(“Employee.Person”) 
         .Include(“Job.Steps”) 
         .Include(“TheWorld.And.ItsDog”) 
         where tr.Id = id 
         select tr).First(); 
    // Calculate has deep knowledge of entity model 
    return EarningsHelpers.Calculate(timeRecord); 
} 

이 방법에 어떤 문제가 있습니까 :

비즈니스 방법의 예제를 고려? 생성 된 SQL은 복잡해질 것입니다. 왜냐하면 우리는 Entity Framework에 Calculate 메소드에서 요구하는 소수의 속성을 얻기 위해 전체 개체의 인스턴스를 구체화하도록 요청했기 때문입니다. 코드도 허약합니다. 모델을 변경하면 (호출 포함을 통해) 열망하는로드가 중단 될뿐만 아니라 Calculate 메소드도 중단됩니다.

단일 책임 원칙 (Single Responsibility Principle)은 클래스가 변경해야하는 이유가 하나만 있어야한다고 명시합니다. 화면에 표시된 예에서 EarningsHelpers 유형은 실제로 수익을 계산하고 엔티티 모델에 대한 변경 사항을 최신 상태로 유지하는 책임이 있습니다. 첫 번째 책임은 정확하고 두 번째 책임은 옳지 않습니다. 우리가 그것을 고칠 수 있는지 보자. 다음 예에서

public Decimal CalculateEarnings(Guid id) 
{ 
    var timeData = from tr in Context.TimeRecords 
        where tr.Id = id 
        select new EarningsCalculationContext 
        { 
         Salary = tr.Employee.Salary, 
         StepRates = from s in tr.Job.Steps 
            select s.Rate, 
         TotalHours = tr.Stop – tr.Start 
        }.First(); 
    // Calculate has no knowledge of entity model 
    return EarningsHelpers.Calculate(timeData); 
} 

, 나는 계산 방법에 대한 인수를 롤업 타입 위에 LINQ 상기 계산 방법으로 필요한 정보의 비트를 골라 쿼리 및 프로젝트 정보를 다시 작성했다. 메서드에 인수를 전달하기 위해 새로운 형식을 작성하는 것이 너무 많은 작업처럼 보였다면 익명 형식으로 투영 할 수 있었고 Salary, StepRates 및 TotalHours를 개별 인수로 전달할 수있었습니다. 그러나 어느 쪽이든 우리는 EarningsHelpers의 엔티티 모델에 대한 종속성을 고정 시켰으며 무료 보너스로보다 효율적인 SQL을 얻었습니다.

이 코드를 살펴보면 TimeRecord의 Job 속성이 nullable 인 경우 어떻게 될지 궁금 할 것입니다. null 참조 예외가 생기지 않습니까?

아니요, 그렇지 않습니다. 이 코드는 IL로 컴파일되고 실행되지 않습니다. 그것은 SQL로 변환 될 것입니다. LINQ to Entities는 null 참조를 통합합니다. 화면에 표시된 예제 쿼리에서 StepRates는 Job이 null이면 null을 반환합니다. 여분의 데이터베이스 쿼리가없는 경우를 제외하고는 지연로드와 동일하다고 생각할 수 있습니다. 코드에 따르면 "일자리가 있으면 그 단계에서 요금을 부과합니다."

이러한 종류의 아키텍처의 또 다른 이점은 웹 어셈블리의 단위 테스트를 매우 쉽게 만들 수 있다는 것입니다. 단위 테스트는 일반적으로 데이터베이스에 액세스하면 안됩니다 (다른 방법으로 데이터베이스에 액세스하는 테스트는 단위 테스트가 아닌 통합 테스트입니다). 실제로 Entity Framework로가는 것이 아니라 Queryables로 객체의 배열을 반환하는 모의 저장소를 작성하는 것은 매우 쉽습니다.

+0

투영 부분이 누락되었습니다. 훌륭한 답변을 주셔서 감사합니다. 비록 내가 철학을 얻는 지 아직 확실하지 않지만. 아이디어는 각 비즈니스 클래스가 L2E를 통해 필요한 데이터를 직접 가져 오는 대신 필요한 모든 데이터를로드하고, 전달하고, 이전 ORM을 장려하는 방식으로 저장합니다. –

+0

아니요, 저는 비즈니스 클래스가 데이터를 직접 가져와야한다고 생각하지 않습니다. 대신, 비즈니스 클래스 (EarningsHelpers 및 EarningsCalculationContext, 내 간단한 예제에서는) 지속성 - 무지해야합니다. 필요한 데이터를 쿼리하고이를 비즈니스 유형에 투영하고이를 비즈니스 메소드에 전달하는 서비스 또는 저장소 계층이 있습니다. 네, 맞습니다. 오랫동안 많은 다른 방법을 사용하여 많은 양의 데이터를 메모리에 보관한다는 아이디어가 마음에 들지 않습니다. 공유 상태가 확장 성의 적이라고 생각합니다. –

관련 문제