2016-09-30 3 views
1

Ich habe einige Probleme mit einer LINQ-Abfrage in C#.Verknüpfen Sie LINQ-Abfrage mit Prädikat

Ich habe in der Datenbank die gleichen Tabellen, die die gleiche Struktur haben. Also, heute habe ich mich mit meiner LINQ-Abfrage beschäftigt.

Weitere Details, ich möchte einige Tabellen mit Prädikaten verbinden.

Ich habe eine Funktion, die zwei Parameter hat. Der erste Parameter ist eine Art von Kontext (z. B. ProductContext, CarContext, CatContext usw.).

Der zweite Parameter ist ein List<something>, dass ich mit meinem ersten Parameter - Context verbinden werde.

Ich möchte nicht eine Reihe von Methoden.

Ich habe die Probe hinzugefügt:

public Element[] GetByIds(MyPredicateContext, Guid[] ids) 
    { 
     return 
      from id in ids 
      join element in MyPredicateContext on id equals element.Id 
      select 
       new Element 
       { 
        Id = element.Id, 
        Description = element.JobDescription, 
       }; 
    } 
+1

Warum wollen Sie einen Kontext als Parameter, und nicht eine Tabelle? Oder willst du beides? Und ich nehme an, dass all Ihre Elemente keine 'JobDescription'-Eigenschaft haben, oder? –

Antwort

0

Wenn die Abfrage richtig ist, eine grundlegende Frage, die ich sehen kann, ist der Rückgabetyp ist Element Array während Sie IEnumerable zurückzukehren versuchen. Möglicherweise kann das Problem durch eine .ToArray() -Option der Ergebnismenge behoben werden.

+0

Ist für diese Frage nicht wichtig – Andrew

+0

Entschuldigung, vielleicht habe ich das Problem hier nicht verstanden, können Sie bitte den genauen Fehler erklären, den Sie erhalten. –

+0

Mann, es ist kein Fehler. Hast du die Beschreibung gelesen? – Andrew

0

Warum nicht

return MyPredicateContext.Where(element=>ids.Contains(element.Id)) 
      .Select(e=>new Element() 
      { 
       Id = element.Id, 
       Description = element.JobDescription 
      }).ToArray(); 
+0

Passen Sie auf, es gab beitreten – Andrew

0

Zu allererst eine neue IQueryable aus einem Array nicht schaffen kann dies dort zu ziehen alles im Speicher und Filter zufällt. Sie arbeiten mit Ausdrücken und nicht mit C# -Code, wenn Sie LINQ mit SQL ausführen, dies funktioniert nur im Speicher (IEnumerable). Ihre Anfrage wird in SQL arbeiten, wenn Sie es wie diese, dass die Art der IQueryable Gegeben

from element in MyPredicateContext 
where ids.Contains(element.Id) 
select new Element 
       { 
        Id = element.Id, 
        Description = element.JobDescription, 
       } 

tun, wo T eine Schnittstelle oder Klasse. Das Ende Methode so etwas wie dieses

public interface IElement 
     { 
      Guid Id { get; } 
      string JobDescription { get; } 
     } 

     public Element[] GetByIds<T>(IQueryable<T> myPredicateContext, Guid[] ids) where T:IElement 
     { 
      return (from element in myPredicateContext 
        where ids.Contains(element.Id) 
        select new Element 
            { 
             Id = element.Id, 
             Description = element.JobDescription, 
            }).ToArray(); 

     } 

aussehen Es gibt Möglichkeiten, es ohne Generics zu tun, aber sie sind ein wenig weiter fortgeschritten und wird beibehalten hart.

Hier ist eine Methode, die auf allen T-Typen funktioniert und richtige IQueryable wird gute SQL produzieren, gerade wie ich hingewiesen habe, ist ein bisschen fortgeschrittener und Sie müssen nachschlagen, wie Ausdruck arbeiten.

public static Element[] GetById<T, Tkey>(IQueryable<T> items,Tkey[] ids) 
     { 
      var type = typeof(T); 
      ParameterExpression param = Expression.Parameter(type); 
      var list = Expression.Constant(ids); 
      //The names of the properties you need to get if all models have them and are named the same and are the same type this will work 
      var idProp = Expression.Property(param, "Id"); 
      var descriptionProp = Expression.Property(param, "JobDescription"); 

      var contains = typeof(Enumerable).GetMethods().First(m => m.Name == "Contains" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(Tkey)); 
      var where = Expression.Lambda<Func<T, bool>>(Expression.Call(contains, list, idProp), param); 

      return (items. 
       Where(where). 
       Select(Expression.Lambda<Func<T, Element>>(
        Expression.MemberInit(
        Expression.New(typeof(Element)), 
         Expression.Bind(typeof(Element).GetProperty("Id"), idProp), 
         Expression.Bind(typeof(Element).GetProperty("Description"), descriptionProp)), 
         param))).ToArray(); 
     } 

Anruf GetById(items, new Guid[] { Guid.NewGuid() })

+0

Achten Sie darauf, gab es beitreten – Andrew

+0

@Andrew Das 'Enthält' tut das gleiche wie Ihre beitreten in diesem Fall. –

+0

@ Filip Cordas. Okay, tut mir leid, es ist mein Fehler, aber wie Klasse von DataBase kann von IElement geerbt werden? – Andrew

Verwandte Themen