2010-05-28 13 views
7

diese Objekte Unter der Annahme ...LINQ to Entities Projektion von verschachtelten Liste

class MyClass 
{ 
    int ID {get;set;} 
    string Name {get;set;} 
    List<MyOtherClass> Things {get;set;} 
} 

class MyOtherClass 
{ 
    int ID {get;set;} 
    string Value {get;set;} 
} 

Wie führe ich eine LINQ to Entities-Abfrage, wie unten einen Vorsprung verwendet wird, das gibt mir eine Liste? Dies funktioniert mit einem IEnumerable (unter der Annahme MyClass.Things ist ein IEnumerable, aber ich brauche Liste verwenden)

MyClass myClass = (from MyClassTable mct in this.Context.MyClassTableSet 
         select new MyClass 
         { 
          ID = mct.ID, 
          Name = mct.Name, 
          Things = (from MyOtherClass moc in mct.Stuff 
             where moc.IsActive 
             select new MyOtherClass 
             { 
              ID = moc.ID, 
              Value = moc.Value 
             }).AsEnumerable() 
         }).FirstOrDefault(); 

Vielen Dank im Voraus für die Hilfe!

Antwort

14

Sie dies nicht tun. Sie müssen diesen Teil in L2O machen.

So könnten Sie tun:

var q = (from MyClassTable mct in this.Context.MyClassTableSet 
     select new // note anonymous type; important! 
     { 
      ID = mct.ID, 
      Name = mct.Name, 
      Things = (from MyOtherClass moc in mct.Stuff 
         where moc.IsActive 
         select new MyOtherClass 
         { 
          ID = moc.ID, 
          Value = moc.Value 
         } 
      }).AsEnumerable(); 

MyClass myClass = (from mct in q 
        select new MyClass 
        {     
         ID = mct.ID, 
         Name = mct.Name, 
         Things = mct.Things.ToList() 
        }).FirstOrDefault(); 

Es gibt keine Art und Weise ist das in einer Abfrage zu tun.

+0

Danke, ich habe es gerade herausgefunden. – ctorx

1

Ich bin mir nicht sicher, was genau Sie fragen, aber List<T> implementiert IEnumerable<T> (das ist nur eine Schnittstelle für eine aufzählbare Sequenz).

Ein Code, der Ihre Projektion tun und haben Dinge, die eine Liste sein, anstelle eines IEnumerable würde die ToList Operator() verwenden, die dieses eine List<T> von jedem IEnumerable<T> erstellt:

MyClass myClass = (from MyClassTable mct in this.Context.MyClassTableSet 
         select new MyClass 
         { 
          ID = mct.ID, 
          Name = mct.Name, 
          Things = (from MyOtherClass moc in mct.Stuff 
             where moc.IsActive 
             select new MyOtherClass 
             { 
              ID = moc.ID, 
              Value = moc.Value 
             }).ToList() 
         }).FirstOrDefault(); 
+1

ToList () auf einer LINQ to Entities Query wird nicht unterstützt, weshalb ich diese Frage gestellt habe. – ctorx

+0

Gibt es eine Referenz dafür? MSDNs eigene LINQ to Entities zeigt, dass Sie tatsächlich ToList verwenden können. http://msdn.microsoft.com/en-us/library/bb896246.aspx?ppud=4 – user7116

+0

Sie können ToList() für das Ergebnis einer Abfrage, aber jetzt innerhalb einer Abfrage verwenden. Im Beispiel Ihrer Verknüpfung wird die ToList() am Ende eines LINQ-Ausdrucks hinzugefügt. In meinem Code ist es in den Ausdruck eingebettet und wird daher nicht unterstützt. – ctorx

-2

Diese Antwort war hilfreich, aber so mache ich es. Dies konvertiert in POCOs und kann unbegrenzt verschachtelte Listen unterstützen. Sehr einfach, aber leistungsstark:

Product product = new Product(); 
List<CoverageCondition> covCondList = null; 
CoverageCondition covCond = null; 
Question question = null; 
List<Question> questList = null; 

var prod = db.PRODUCTs.Include("COVERAGE_CONDITION.QUESTIONs").Where(p => p.PRODUCT_CODE == productCode).FirstOrDefault(); 

product.ProductId = prod.PRODUCT_ID; 
product.ProductCode = prod.PRODUCT_CODE; 
product.ProductName = prod.PRODUCT_NAME; 

// go through coverage conditions 
covCondList = new List<CoverageCondition>(); 
product.CoverageConditions = covCondList; 
foreach (COVERAGE_CONDITION cc in prod.COVERAGE_CONDITION) 
{ 
    covCond = new CoverageCondition(); 
    covCond.ConditionId = cc.COV_CONDITION_ID; 
    covCond.ConditionCode = cc.COV_CONDITION_CODE; 
    covCond.ConditionName = cc.COV_CONDITION_NAME; 
    covCondList.Add(covCond); 

    // go through questions for each coverage condtion, if any 
    questList = new List<Question>(); 
    covCond.Questions = questList; 
    foreach (QUESTION q in cc.QUESTIONs) 
    { 
     question = new Question(); 
     question.QuestionId = q.QUESTION_ID; 
     question.QuestionCode = q.QUESTION_CODE; 
     question.QuestionText = q.QUESTION_TEXT; 
     questList.Add(question); 
    } 
} 
0

Bitte sehen Sie sich folgende Lösung an. Sie können in Ihrer Klasse Felder für List und IEnumerable trennen:

MyClass myClass = (from MyClassTable mct in this.Context.MyClassTableSet 
        select new MyClass 
        { 
         ID = mct.ID, 
         Name = mct.Name, 
         ThingsForLinq = (from MyOtherClass moc in mct.Stuff 
            where moc.IsActive 
            select new MyOtherClass 
            { 
             ID = moc.ID, 
             Value = moc.Value 
            }).AsEnumerable() 
        }).FirstOrDefault(); 

Und verwenden Sie Dinge später:

class MyClass 
{ 
    ... 

    List<MyOtherClass> m_Things = new List<MyOtherClass>(); 
    public List<MyOtherClass> Things 
    { 
     get 
     { 
      if (ThingsForLinq != null) 
      { 
       m_Things = ThingsForLinq.ToList(); 
       ThingsForLinq = null; 
      } 
      return m_Things; 
     } 
     set 
     { 
      m_Things = value; 
     } 
    } 

    public IEnumerable<MyOtherClass> ThingsForLinq { get; set; } 
} 

So Sie ThingsForLinq in EF Linq Abfragen verwendet haben

myClass.Things.Add(...)