programing

엔티티 그룹 기준(OUTER APPLY)에 대한 링크 "oracle 11.2.0.3.0은 적용을 지원하지 않습니다."

lastmoon 2023. 7. 21. 21:52
반응형

엔티티 그룹 기준(OUTER APPLY)에 대한 링크 "oracle 11.2.0.3.0은 적용을 지원하지 않습니다."

아래에 제품 목록을 조회하는 코드 샘플이 있습니다.

 var productResults = Products.Where((p) => refFilterSequence.Contains(p.Ref))
                .GroupBy(g => g.Code, (key, g) => g.OrderBy(whp => whp.Ref).First()).ToList();


이것은 예상대로 정확히 작동하며 in 메모리 컬렉션을 사용할 때는 원하는 4개의 행을 반환하지만 Oracle 데이터베이스에 대해 실행할 때는 다음과 같습니다.

.GroupBy(g => g.Code, (key, g) => g.OrderBy(whp => whp.Ref).First())

사용해야 한다는 오류가 발생합니다.FirstOrDefaultOracle 데이터베이스에서는 지원되지 않습니다.oracle 11.2.0.3.0이 apply를 지원하지 않습니다라는 오류가 발생했습니다.Google은 CodePlex: https://entityframework.codeplex.com/workitem/910 에서 이를 확인할 수 있습니다.

이 문제는 다음 이진 파일을 사용할 때 발생합니다.

  • 엔티티 프레임워크 6.0.0.0
  • Oracle.ManagedDataAccess 4.121.2.0
  • Oracle.ManagedDataAccess.엔티티 프레임워크 6.121.2.0
  • .Net Framework 4.5.1

데이터베이스는 Oracle 11.2.0.3.0 데이터베이스입니다.

생성된 sql은 11.2.0.3.0 버전의 Oracle에서 지원되지 않는 OUTER APPLY(아래 이미지 참조)를 사용하는데 왜 EF/Oracle입니까?Managed Data Access를 사용하려고 합니까?EF에게 APPLY 키워드를 사용하지 말라고 할 수 있는 방법이 있습니까?

SQL

아래 페이지에는 Oracle 12c Release 1에 APPLY 지원이 추가되었다고 나와 있지만 GROUP BY 작업을 위해 모든 데이터베이스를 업데이트할 수는 없습니다.http://www.oracle.com/technetwork/database/windows/newfeatures-084113.html

이 문제는 알려진 문제(Entity Framework에 대한 SqlClient의 알려진 문제)인 것 같습니다.

다음은 출력 쿼리에 CROSS APPLE 및/또는 OUTER APPLE 연산자가 포함될 수 있는 몇 가지 일반적인 시나리오입니다.

  • LINQ는 요소 선택기를 수락하는 그룹화 방법을 사용하는 쿼리를 수행합니다.

보기 작성에 의존하기 전에(여러 데이터베이스에 보기를 작성해야 할 경우) 다른 솔루션을 볼 수 있는 사람이 있습니까?

이 데이터베이스 버전에 대해 원하는 작업을 수행할 수 있는 SQL은 다음과 같습니다.

select *
from ( select  RANK() OVER (PARTITION BY sm.product ORDER BY refs.map)      ranking, sm.*
            from    schema.table sm,
                    (
                        select 'R9' ref, 0 map from dual
                        union all
                        select 'R1' ref, 1 map from dual
                        union all
                        select 'R6' ref, 2 map from dual
                    ) refs
            where   sm.ref= refs.ref                               
          ) stock
where ranking  = 1

코드는 결국 웹 API의 OData 컨트롤러에 전달되는 서비스 클래스에 있게 됩니다.아래 예제는 데모 데이터를 사용하고 실제 데이터베이스에는 700,000개의 레코드가 있으므로 쿼리 실행을 피하고 OData가 페이지 제한 및 추가 필터링을 처리하도록 하고 싶습니다.

using System;
using System.Collections.Generic;
using System.Linq;

namespace DemoApp
{
    class Program
    {
        public class Product
        {
            public string Ref { get; set; }
            public string Code { get; set; }
            public int Quantity { get; set; }
        }

        //demo data
        static readonly List<Product> Products = new List<Product>
        {
            new Product { Ref = "B2", Code = "ITEM1", Quantity = 1},
            new Product { Ref = "R1", Code = "ITEM1", Quantity = 2},
            new Product { Ref = "R9", Code = "ITEM1", Quantity = 3},
            new Product { Ref = "R9", Code = "ITEM2", Quantity = 4},
            new Product { Ref = "R6", Code = "ITEM2", Quantity = 5},
            new Product { Ref = "B2", Code = "ITEM3", Quantity = 6},
            new Product { Ref = "R1", Code = "ITEM3", Quantity = 7},
            new Product { Ref = "R9", Code = "ITEM3", Quantity = 8},
            new Product { Ref = "B2", Code = "ITEM4", Quantity = 9},
            new Product { Ref = "X3", Code = "ITEM4", Quantity = 10},
            new Product { Ref = "B8", Code = "ITEM5", Quantity = 10},
            new Product { Ref = "R6", Code = "ITEM5", Quantity = 12},
            new Product { Ref = "M2", Code = "ITEM5", Quantity = 13},
            new Product { Ref = "R1", Code = "ITEM5", Quantity = 14},
        };

    static void Main(string[] args)
    {
        // this array is of variable length, and will not always contain 3 items.
        var refFilterSequence = new List<string> {"R9", "R1", "R6"};

        var results = GetProductsForODataProcessing(refFilterSequence);

        // some further filtering may occur after the queryable is returned.
        // the actual implmentation is an OData Web API, so filters, expansions etc could be added.

        //results = results.Where(p => p.Quantity > 2);

        results.ToList().ForEach(p => Console.WriteLine("RANK:{0}\tREF:{1}\tCode:{2}\tQty:{3}", "?", p.Ref, p.Code, p.Quantity));
        Console.ReadLine();
    }

    static IQueryable<Product> GetProductsForODataProcessing(List<string> filterSequence )
    {
        var productResults = Products.Where((p) => filterSequence.Contains(p.Ref))
            .GroupBy(g => g.Code, (key, g) => g.OrderBy(whp => whp.Ref).First()).AsQueryable();

        return productResults;               
    }
}


// Example Output
// .......................
// REF:R1 Code:ITEM1 Qty:2
// REF:R6 Code:ITEM2 Qty:3
// REF:R1 Code:ITEM3 Qty:7
// REF:R1 Code:ITEM5 Qty:14

당신이 직접 쿼리를 작성할 수 있었기 때문입니다.저장 프로시저를 생성하여 Entity Framework에서 SP를 호출할 수 있습니다.

GroupBy 이전에 ToArray를 실행하여 메모리에서 실행할 수 있습니다.최적의 성능은 아니지만 작동해야 합니다.

 var productResults = Products.Where((p) => refFilterSequence.Contains(p.Ref)).ToArray()
                    .GroupBy(g => g.Code, (key, g) => g.OrderBy(whp => whp.Ref).First()).ToList();

Oracle 11은 APPLY를 지원하지 않습니다.그러나 Oracle 12는 이를 지원합니다.

언급URL : https://stackoverflow.com/questions/29705013/linq-to-entities-group-by-outer-apply-oracle-11-2-0-3-0-does-not-support-appl

반응형