2012-11-16 3 views
1

지금은 간단한 문제로 2 일간 만만찮은 시도를하고 있습니다.Extension on IQueryable에는 SQL 로의 번역이 없습니다

제품 엔터티 및 ProductLocationHistory 엔터티가있는 데이터베이스가 있습니다. ProductLocationHistory에는 창고, 연락처 또는 관계에 대한 참조가 있습니다. 제품을 옮길 때마다 제품의 과거를 추적 할 수 있도록 새로운 항목이 추가됩니다. 따라서 현재 위치는 ProductLocationHistory의 DateCreation 필드에 의해 결정된 마지막 항목입니다.

예 :

var storehousesWithBorrowedItems = productService.GetAllProducts() 
    .Select(p => p.ProductLocationHistories 
     .SingleOrDefault(plh => plh.DateCreation == p.ProductLocationHistories.Max(grp => grp.DateCreation))) 
    .Select(plh => plh.Storehouse) 
    .Distinct(); 

이 현재 제품이 모든 창고입니다.

물론 제품의 현재 위치를 결정할 때마다 코드에이 코드를 작성하는 것은 매우 불편합니다. 제품의 현재 ProductLocationHistory에 대한 참조는 일관성 문제로 인해 제 의견으로는 완전히 바람직하지 않습니다. 내가 노력 그래서

Product.ProductLocationHistories.Current(); 

:처럼 뭔가를 원합니다 내가 및 제품의 결합 포트폴리오 현재는 SQL에 지원되는 변환이 없습니다 '먹을수록이 된 쿼리에서 작동하지 않습니다

public static ProductLocationHistory Current(this EntitySet<ProductLocationHistory> plhs) 
    { 
     return plhs.SingleOrDefault(plh => plh.DateCreation == plhs.Max(grp => grp.DateCreation)); 
    } 

ProductLocationHistory는 종종 IEnumerable 대신 IQueryable에 머무르고 각 제품에 대한 쿼리를 통해 현재 위치를 확인하려는 쿼리의 '시작'입니다. 이후에 뒤따라 오는 것은 무엇입니까? ... 어떤 엔티티에 대한 현재 로그 항목이 자주 사용되며 .Current() 함수가 작동하고 쿼리 가능한 상태로 유지되는 한 많은 복잡한 것은 중요하지 않습니다. 내 .Current (...) 함수는 기본 코드를 쿼리 할 수 ​​있기 때문에 작동 할 것이라고 기대했지만 여전히 예외가 발생합니다. 첫 번째 예제처럼 코드가 인라인 될 때 ​​예외가 발생하지 않습니다.

나는 Func, ProductLocationHistory >>와 같은 가능성을 겪었으며, 표현식은 < ...> 주위에도 있지만 나는 내가 찾고있는 예를 찾을 수 없었다. Product.CurrentProductLocationHistory()와 같은 종류의 솔루션이 더 좋을 수도 있습니다. 절대 가장 좋은 방법은 훨씬 더 일반적인하고 것 형태의 :

Current<T> (IQueryable<T> collection, string field) { return entity with max field of collection } 

도움을 크게, 나는 오랫동안이 작업을 시도하고있다 주시면 감사하겠습니다 그리고 그것이의 내부 기능 때문에 가능해야 확실 해요 LINQ 자체 - Any, First, Count, Max - 필요한 경우 쿼리 가능 상태를 유지합니다.

업데이트 현재

, 다음 작품 :

Expression<Func<Product, ProductLocationHistory>> expression = IQueryable.Current(null); 
     var ken = productService.GetAllProducts() 
      .Where(p => p.OnLoan) 
      .Select(expression) 
      .Where(plh => plh.Storehouse != null) 
      .Select(plh => plh.Storehouse) 
      .Distinct(); 

public static Expression<Func<Product, ProductLocationHistory>> Current(this EntitySet<ProductLocationHistory> productLocationHistories) 
    { 
     Expression<Func<Product, ProductLocationHistory>> expression = p => p.ProductLocationHistories 
             .SingleOrDefault(plh => plh.DateCreation == p.ProductLocationHistories.Max(plhs => plhs.DateCreation)); 
     return expression; 
    } 

올바른 방향으로 단계,하지만 난 아직 완전히 만족하지 않다. p.ProductLocationHistories()를 사용할 수 있기를 원합니다. 현재() 내 퀘스트가 계속됩니다.

감사합니다. 이미 Kirill! SQL로 변환 된 C# 코드를 처음 보았습니다! 올바른 방향으로 나아가십시오!

Expression<Func<ProductLocationHistory, bool>> currentSelector = plh => plh.DateCreation == p.ProductLocationHistories.Max(grp => grp.DateCreation) 

를 어디서나 사용 :

+0

를 장소에이 확장 방법을 사용하면 * * 아니에요 경우 .Current()를 호출 할 수 있습니다 착각. 사용하려는 호출 규칙 샘플을 보여줄 수 있습니까? 또한'OrderOlyDefault'를 사용하여 max를 쿼리하는 것보다 OrderByDescending (pld => pld.DateCreation) .FirstOrDefault()를 사용하는 것이 훨씬 빠릅니다. – jessehouwing

+0

ASP.NET 4.5로 업그레이드하자 마자 해결책 [link] (http://stackoverflow.com/questions/10826275/iqueryable-extension-method-for-linq2entities)을 시도 할 것입니다. 현재 Visual Studio 2012를 구입 중입니다. 나중에이 질문을 업데이트 할 수 있습니다. – Paul1977

답변

1

당신은 표현으로 필드를 설정할 수 있습니다

var storehousesWithBorrowedItems = productService.GetAllProducts() 
    .Select(p => p.ProductLocationHistories 
     .SingleOrDefault(currentSelector)) 
    .Select(plh => plh.Storehouse) 
    .Distinct(); 
+0

내가 도움이된다면 대답을 받아 들일 것. –

+0

지금까지 나는이 기능을 기억하고 있지만, 내가 원하는만큼 쓸모가 없다. .Current()는 로그에서 자주 사용되며이 문제를 해결하는 데 필요한만큼 갈 의향이 있습니다. 자신 만의 쿼리 가능한 함수를 작성할 가능성이 없다는 이유로 부끄러운 Microsoft. 나는 그것이 아주 생략 된 것 같은데. 나머지의 경우, LINQ는 동적 SQL 텍스트 문자열 * br *을 사용하여 이전보다 훨씬 쉽고 편리하게 만듭니다. – Paul1977

관련 문제