IT

LINQ to Entities에서는 매개 변수가없는 생성자와 이니셜 라이저 만 지원됩니다.

lottoking 2020. 7. 10. 07:42
반응형

LINQ to Entities에서는 매개 변수가없는 생성자와 이니셜 라이저 만 지원됩니다.


이 linq에서는 오류가 있습니다.

var naleznosci = (from nalTmp in db.Naleznosci
                              where nalTmp.idDziecko == idDziec
                              select new Payments
                              (
                                  nalTmp.Dziecko.Imie,
                                  nalTmp.Dziecko.Nazwisko,
                                  nalTmp.Miesiace.Nazwa,
                                  nalTmp.Kwota,
                                  nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                                  nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                  nalTmp.DataRozliczenia,
                                  nalTmp.TerminPlatnosci
                              )).ToList();

이 문제를 어떻게 해결합니까? 나는 표현의 조합으로 시도합니다 ... : /


'결제'에 대한 자세한 정보가 무엇이든 크게 도움이되지 않지만 결제를 기반으로 구성되는 속성 일부를 설정 가정합니다.

var naleznosci = (from nalTmp in db.Naleznosci
                              where nalTmp.idDziecko == idDziec
                              select new Payments
                              {
                                  Imie = nalTmp.Dziecko.Imie,
                                  Nazwisko = nalTmp.Dziecko.Nazwisko,
                                  Nazwa= nalTmp.Miesiace.Nazwa,
                                  Kwota = nalTmp.Kwota,
                                  NazwaRodzajuOplaty = nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                                  NazwaTypuOplaty = nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                  DataRozliczenia = nalTmp.DataRozliczenia,
                                  TerminPlatnosci = nalTmp.TerminPlatnosci,
                              }).ToList();

당신은 여전히 ​​(경우 에이 문제가 초기화 목적으로 요구되는) 초기화하지 속성에 대한 생성 사용하려는 경우, 호출하여 쿼리를 열거 ToList()ToArray(), 다음 Select(…). 컬렉션를 사용하며 변수가있는 생성 호출 할 수있는 호출 제한 에 따라서 LINQ 사라집니다 Select(…).

따라서 코드는 다음과 소비됩니다.

var naleznosci = db.Naleznosci
                          .Where(nalTmp => nalTmp.idDziecko == idDziec)
                          .ToList() // Here comes transfer to LINQ to Collections.
                          .Select(nalImp => new Payments
                              (
                                  nalTmp.Dziecko.Imie,
                                  nalTmp.Dziecko.Nazwisko,
                                  nalTmp.Miesiace.Nazwa,
                                  nalTmp.Kwota,
                                  nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                                  nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                  nalTmp.DataRozliczenia,
                                  nalTmp.TerminPlatnosci
                              ))
                          .ToList();

이전이 오류가 발생하면 Payment유형이 다음 변수 인 경우 요청 된 변수가없는 struct생성 튼 지원하지 않기 때문에 오류가 방금 보관 생각했습니다 struct.

이 경우 Payment클래스 로 변환 하고 객체 초기화 구문을 사용하면 문제가 해결됩니다.


나와 같고 작성중인 각 쿼리에 대해 문제를 해결하는 다른 방법이 있습니다.

var query = from orderDetail in context.OrderDetails
            join order in context.Orders on order.OrderId equals orderDetail.orderId
            select new { order, orderDetail };

이제 익명 오브젝트를 포함하는 IQueryable이 있습니다. 사용자 정의를 생성자로 채우려면 다음과 같이하면됩니다.

return query.ToList().Select(r => new OrderDetails(r.order, r.orderDetail));

이제 사용자 정의 개체 (두 개체를 매개 변수로 사용)는 필요에 따라 속성을 채울 수 있습니다.


먼저 해결을 피할 것입니다.

from ....
select new Payments
{
  Imie = nalTmp.Dziecko.Imie,
  ....
}

이것은 생성 될 필요로하는 캡슐화를 무시하고 새로운 Payments ()는 데이터가없는 유효한 지불이라고 말하지만 값은 도메인에 따라 최소한 의과 필수 필드를 가져옵니다.

필수 필드에 필요한 데이터 만 가져옵니다.

from ....
select new
{
  Imie = nalTmp.Dziecko.Imie,
  Nazwisko = nalTmp.Dziecko.Nazwisko
  ....
}
.ToList() // Here comes transfer to LINQ to Collections.
.Select(nalImp => new Payments
 (
  nalTmp.Imie,//assume this is a required field
  ...........
  )
  {
     Nazwisko = nalTmp.Nazwisko //optional field
  })
.ToList();

확장 방법을 사용하여 동일하게 시도 할 수 있습니다. 데이터베이스 사용 제공자는 무엇입니까?

var naleznosci = db.Naleznosci
                          .Where<TSource>(nalTmp => nalTmp.idDziecko == idDziec)
                          .Select<TSource, TResult>(
                             delegate(TSource nalTmp) { return new Payments
                             (
                                 nalTmp.Dziecko.Imie,
                                 nalTmp.Dziecko.Nazwisko,
                                 nalTmp.Miesiace.Nazwa,
                                 nalTmp.Kwota,
                                 nalTmp.RodzajeOplat.NazwaRodzajuOplaty,
                                 nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                 nalTmp.DataRozliczenia,
                                 nalTmp.TerminPlatnosci
                             ); })
                          .ToList();

그냥 ToList()DbSet전과 Select문 .. 실제는 DbSet쿼리로 저장, 아직없는 것. 호출 한 후에 ToList()는 개체를 가지고 있고 쿼리에서 기본이 아닌 생성 라이선스를 사용할 수 있습니다.

사용 시간에 가장 수단은 방법은 작은 세트의 옵션입니다.


그래, 이렇게 해봐 ....

var naleznosci = (from nalTmp in db.Naleznosci
                              where nalTmp.idDziecko == idDziec
                              select new Payments()
                              {
                                  Dziecko.Imie,
                                  Dziecko.Nazwisko,
                                  Miesiace.Nazwa,
                                  Kwota,
                                  RodzajeOplat.NazwaRodzajuOplaty,
                                  RodzajeOplat.TypyOplat.NazwaTypuOplaty,
                                  DataRozliczenia,
                                  TerminPlatnosci
                              }).ToList();

다음 중괄호에서 생성 된 속성을 초기화합니다. { }


앞서 언급 한 한 방법 외에도 다음과 같이 Enumerable 컬렉션으로 구문 분석 할 수 있습니다.

(from x in table
....
).AsEnumerable()
.Select(x => ...)

이것은 또한 다음과 같이 익명 객체를 만들 때 삶을 더 쉽게 만드는 추가 이점이 있습니다.

 (from x in tableName
select x.obj)
.Where(x => x.id != null)
.AsEnumerable()
.Select(x => new {
   objectOne = new ObjectName(x.property1, x.property2),
   parentObj = x
})
.ToList();

그러나 컬렉션을 Enumerable로 구문 분석하면 컬렉션을 메모리로 가져 오는 스타일 리소스 집약적 일 수 있습니다. 여기서주의해야합니다.


또한 여러 개체가있는 생성 튼 사용하여 초기화하려는 경우 Linq에서 값을 반환하지 않습니다.

따라서 다음과 같이 할 수 있습니다.

(from x in table_1
   join y in table_2
   on x.id equals y.id
   select new {
   val1 = x,
   val2 = y
})
.DefaultIfEmpty()
.ToList()
.Select(a => new Val_Constructor(a.val1 != null ? a.val1 : new Val_1_Constructor(),
                            a.val2 != null ? a.val2 : new Val_2_Constructor()))
.ToList();

미안 계획 후 파티에 늦게해야 할 생각, 대한 , 나는 그것이 가장 빠른 메모리 절약 구현 내가 수있는 가장 빠른 메모리를 공유 할 수 있습니다.

귀하의 예에 맞게 다음과 같이 작성하십시오.

public static IQueryable<Payments> ToPayments(this IQueryable<Naleznosci> source)
{
  Expression<Func<Naleznosci, Payments>> createPayments = naleznosci => new Payments
  {
    Imie = source.Dziecko.Imie,
    Nazwisko = source.Dziecko.Nazwisko,
    Nazwa= source.Miesiace.Nazwa,
    Kwota = source.Kwota,
    NazwaRodzajuOplaty = source.RodzajeOplat.NazwaRodzajuOplaty,
    NazwaTypuOplaty = source.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
    DataRozliczenia = source.DataRozliczenia,
    TerminPlatnosci = source.TerminPlatnosci,
  };

  return source.Select(createPayments);
}

여기에서 큰 장점은 (Daien Guard가 링크의 주석에서 지적했듯이)

  • 보관할 때마다 초기화 패턴을 사용하지 못하도록합니다.
  • 를 통해 사용 var foo = createPayments(bar);뿐만 아니라 myIQueryable.ToPayments를 통해 사용 () 수.

나는 오늘 같은 문제가 있지만 내 솔루션은 Yoda가 준비한 것과 충돌했지만 유창한 구문 작동합니다.

내 솔루션을 코드에 적용 : 다음 정적 메소드를 개체 클래스에 추가했습니다.

    /// <summary>
    /// use this instead of a parameritized constructor when you need support
    /// for LINQ to entities (fluent syntax only)
    /// </summary>
    /// <returns></returns>
    public static Func<Naleznosci, Payments> Initializer()
    {
        return n => new Payments
        {
             Imie = n.Dziecko.Imie,
             Nazwisko = n.Dziecko.Nazwisko,
             Nazwa = n.Miesiace.Nazwa,
             Kwota = n.Kwota,
             NazwaRodzajuOplaty = n.RodzajeOplat.NazwaRodzajuOplaty,
             NazwaTypuOplaty = n.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
             DataRozliczenia = n.DataRozliczenia,
             TerminPlatnosc = n.TerminPlatnosci
        };
    }

그런 다음 기본 쿼리를 다음과 같이 업데이트했습니다.

var naleznosci = (from nalTmp in db.Naleznosci
    where nalTmp.idDziecko == idDziec
    select new Payments.Initializer());

이 클래스 / 데이터 전송 개체에 멤버의 부풀림을 푸시 초기화를 가진 James Manning의 솔루션과 전송이 동일합니다.

참고 : 원래는 "Initializer"보다 더 설명하는 이름을 사용했지만 검토 한 결과 "Initilizer"로 의미하는 것을 알았습니다 (적어도 내 목적에는).

최종 참고 사항 :
이 솔루션을 처음으로 원래는 동일한 코드를 공유하는 구문을 작동하도록 간단하게 생각하고 조정했습니다. 나는 더 이상 그것이 사실이라고 믿지 않습니다. 적합한 유형의 속기 구성을 사용하는 클래스가있는 방식으로 클래스 자체에 적합한 수있는 메소드가 필요하다고 생각합니다.

쿼리 구문의 경우 확장 메서드 (또는 사용되는 기본 클래스 외부의 메서드)가 필요합니다. (쿼리 구문은 T가 아닌 IQueryable을 작동하기를 원하기 때문에)

다음은 마지막으로 쿼리 구문에서 작동하도록하는 데 샘플입니다. (요다가 이미 못을 박았지만 처음에는 이해하지 기 쓰기 때문에 사용이 더 명확 할 것)

/// <summary>
/// use this instead of a parameritized constructor when you need support
/// for LINQ to entities (query syntax only)
/// </summary>
/// <returns></returns>
public static IQueryable<Payments> Initializer(this IQueryable<Naleznosci> source)
{
    return source.Select(
        n => new Payments
        {
            Imie = n.Dziecko.Imie,
            Nazwisko = n.Dziecko.Nazwisko,
            Nazwa = n.Miesiace.Nazwa,
            Kwota = n.Kwota,
            NazwaRodzajuOplaty = n.RodzajeOplat.NazwaRodzajuOplaty,
            NazwaTypuOplaty = n.RodzajeOplat.TypyOplat.NazwaTypuOplaty,
            DataRozliczenia = n.DataRozliczenia,
            TerminPlatnosc = n.TerminPlatnosci
    };
}

및 사용법

var naleznosci = (from nalTmp in db.Naleznosci
    where nalTmp.idDziecko == idDziec
    select nalTmp).Initializer().ToList();

대답하기는 늦었지만 여전히 고통받는 사람을 수 있습니다. LINQ to 엔터티는 변수없는 개체 생성을 지원하지 않습니다. 그러나 IEnumerable 의 프로젝션 메소드는 .

따라서 선택하기 전에 다음 코드를 사용하여 IQueryableIEnumerable 로 변환하십시오 .

var result = myContext.SomeModelClass.AsEnumerable().Select(m => m.ToString());

잘 작동합니다. 그러나 그러나 물론 쿼리의 이점을 잃게됩니다.

참고 URL : https://stackoverflow.com/questions/3571084/only-parameterless-constructors-and-initializers-are-supported-in-linq-to-entiti

반응형