문제

단일 LINQ 쿼리를 사용하여 LINQ에서 엔티티의 하위 요소를 필터링해야합니다. 이게 가능해?

두 개의 관련 테이블이 있다고 가정합니다. 구절과 versetranslations. LINQ에서 SQL에 의해 생성 된 엔티티는 Versetranslation 모음 인 Child Object를 포함하는 구절 객체를 갖는 것입니다.

이제 다음 linq 쿼리가 있다면

var res = from v in dc.Verses
                  where v.id = 1
                  select v;

나는 ID가 1 인 구절 모음을 얻고 각 구절 대상에는 세대의 모든 어린이 대상이 포함되어 있습니다.

제가하고 싶은 것은 자식 구절 목록을 필터링하는 것입니다.

지금까지 내가 생각해 낼 수있는 유일한 방법은 익명의 새로운 유형을 사용하는 것입니다. 다음과 같이

var res= from v in dc.Verses
                   select new myType
                   {
                       VerseId = v.VerseId,
                       VText = v.Text,
                       VerseTranslations = (from trans in v.VerseTranslations
                                               where languageId==trans.LanguageId
                                               select trans
                   };

위의 코드는 작동하지만 새로운 클래스를 선언해야했습니다. 자식 테이블의 필터링을 첫 번째 LINQ 쿼리에 통합하여 새 클래스를 선언 할 필요가 없도록하는 방식으로 수행 할 방법이 없습니까?

안부, Mac

도움이 되었습니까?

해결책

그래서 나는 Shiraz의 포인터 덕분에 마침내 일을하게되었습니다.

        DataLoadOptions options = new DataLoadOptions();
        options.AssociateWith<Verse>(item => item.VerseTranslation.Where(t => languageId.Contains(t.LanguageId)));

        dc.LoadOptions = options;

        var res = from s in dc.Verse
                   select s;

이것은 새로운 확장 클래스를 투영하거나 사용하지 않아도됩니다.

모든 의견을 보내 주셔서 감사합니다.

다른 팁

객체의 동봉 된 모음에서 필터링,

var res = dc.Verses
            .Update(v => v.VerseTranslations 
                      =  v.VerseTranslations
                          .Where(n => n.LanguageId == languageId));

확장 방법 "업데이트"에서 후드 곤 린크

public static class UpdateExtensions {

    public delegate void Func<TArg0>(TArg0 element);

    /// <summary>
    /// Executes an Update statement block on all elements in an IEnumerable<T> sequence.
    /// </summary>
    /// <typeparam name="TSource">The source element type.</typeparam>
    /// <param name="source">The source sequence.</param>
    /// <param name="update">The update statement to execute for each element.</param>
    /// <returns>The numer of records affected.</returns>
    public static int Update<TSource>(this IEnumerable<TSource> source, Func<TSource> update) {
        if (source == null) throw new ArgumentNullException("source");
        if (update == null) throw new ArgumentNullException("update");
        if (typeof(TSource).IsValueType) 
            throw new NotSupportedException("value type elements are not supported by update.");

        int count = 0;
        foreach(TSource element in source) {
            update(element);
            count++;
        }
        return count;
    }
}

이것이 데이터베이스에서 나오면 첫 번째 명령문을 실행할 수 있습니다.

그런 다음 WHERE 절을 가진 부하 또는 verseTranslation을 포함하십시오.

http://msdn.microsoft.com/en-us/library/bb896249.aspx

당신은 당신의 모델에서 구절과 versetranslations 사이의 관계가 있습니까? 이 경우 작동 할 수 있습니다.

var res= from v in 
dc.Verses.Include("VerseTranslations").Where(o => languageId==o.LanguageId)
select v;

자식 테이블의 필터링을 첫 번째 LINQ 쿼리에 통합하여 새 클래스를 선언 할 필요가 없도록 할 수있는 방법이 없습니까?

기술적으로 대답은 아니오입니다. 단일 엔티티 객체 (구절, versetranslation)보다 더 많은 데이터를 반환하려고한다면 "프로젝트"에 어떤 종류의 개체가 필요합니다. 그러나 명시 적으로 선언 할 수 있습니다 myType 익명 유형을 사용하여 :

var res = from v in dc.Verses
          select new
          {
              Verse = v,
              Translations = (from trans in v.VerseTranslations
                              where languageId==trans.LanguageId
                              select trans).ToList()
          };

var first = res.First();
Console.WriteLine("Verse {0} has {1} translation(s) in language {2}.",
    first.Verse.VerseId, first.Translations.Count, languageId);

컴파일러는 적절한 구절과 번역 속성을 가진 클래스를 생성합니다. 이름별로 유형을 참조 할 필요가없는 한이 객체를 거의 모든 것에 사용할 수 있습니다 (예 : 이름이 지정된 메소드에서 돌아 오기 위해). 따라서 기술적으로 유형을 "선언"하지는 않지만 여전히 사양에 따라 생성 될 새로운 유형을 사용하고 있습니다.

단일 LINQ 쿼리를 사용하는 한, 데이터를 구성하는 방식에 따라 다릅니다. 나에게 원래 쿼리가 가장 의미가있는 것 같습니다. Verse 번역 필터링 목록이 있습니다. 언어 당 하나의 번역만을 기대하면 사용할 수 있습니다. SingleOrDefault (또는 FirstOrDefault) 하위 쿼리를 평평하게하거나 SelectMany 이와 같이:

var res= from v in dc.Verses
         from t in v.VerseTranslations.DefaultIfEmpty()
         where t == null || languageId == t.LanguageId
         select new { Verse = v, Translation = t };

구절에 여러 번역이 있으면 각 구절/번역 쌍에 대해 "행"을 반환합니다. 나는 사용한다 DefaultIfEmpty() 왼쪽 가입으로서 번역이없는 경우에도 모든 구절을 얻을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top