2011-01-17 13 views
2

Dieser Code mich nervt,unsicher über diesen Code, hat Code Geruch!

Ich habe ein eigenes Objekt EventDistance aber ich denke, es ist wahrscheinlich nicht erforderlich, es ist nur, dass im nicht sicher, wie es anders zu codieren. Entfernung ist eine Eigenschaft, die ich zu einer Teilklasse für Event hinzugefügt habe. Grundsätzlich möchte ich alle Ereignisse zurückgeben und nach Entfernung sortieren.

Im die Extrarunde foreach Denken ist vielleicht unnötig.

public IQueryable<Event> FindByLocation(float latitude, float longitude) 
     { 

      var eventsList = from ev in GetAllEvents() 
          join i in db.NearestEvents(latitude, longitude) 
          on ev.ID equals i.ID 
          select new EventDistance() { TheEvent = ev, Distance = i.Distance }; 


      foreach (var item in eventsList) 
      { 
       item.TheEvent.Distance = item.Distance; 
      } 
      return eventsList.OrderBy(e => e.Distance).Select(e => e.TheEvent); 
     } 

Antwort

1

sollten Sie nicht brauchen die EventDistance Klasse, von dem, was ich sehen kann. einen anonymen Typs auslassen einfach, und Verwendung durch keine Art in Ihrem LINQ Ausdruck spezifiziert:

public IQueryable<Event> FindByLocation(float latitude, float longitude) 
    { 

     var eventsList = from ev in GetAllEvents() 
         join i in db.NearestEvents(latitude, longitude) 
         on ev.ID equals i.ID 
         select new { TheEvent = ev, Distance = i.Distance }; 


     foreach (var item in eventsList) 
     { 
      item.TheEvent.Distance = item.Distance; 
     } 
     return eventsList.OrderBy(e => e.Distance).Select(e => e.TheEvent); 
    } 
1

Ich bin ahnungslos mit dieser LINQ-Syntax, aber es sollte wirklich möglich sein, den Abstandswert im ersten aufzufüllen select. Etwas wie

var eventsList = from ev in GetAllEvents() 
       join i in db.NearestEvents(latitude, longitude) 
       on ev.ID equals i.ID 
       orderby i.Distance 
       select (ev => { ev.Distance = i.Distance; return ev; }); 

? Oder geschrieben richtig :-)

var eventsList = GetAllEvents() 
       .Join(db.NearestEvents(latitude, longitude), 
         ev => ev.ID, 
         i => i.ID, 
         (ev, i) => { ev.Distance = i.Distance; return ev; }) 
       .OrderBy(ev => ev.Distance); 

N. B. als qstarin Kommentare unten ist dies nur möglich, wenn wir auf Objekte an diesem Punkt handeln, nicht ORM-Objekte, die als SQL ausgewertet werden. Das heißt, können Sie wahrscheinlich noch

  1. die orderby tun in der Anfangs holen
  2. Kraft, um die Objekte in den Speicher (ich vergessen, der beste Weg, dies zu tun)
  3. eine einzelne select verwenden, um die Objekte zu kombinieren, in das Ereignisobjekt wie oben, statt eine Schleife
+0

Dies wird wahrscheinlich nicht funktionieren, wenn der LINQ-Ausdruck von einem Provider behandelt wird, der versucht, es in SQL zu übersetzen. Wenn es bei In-Memory-Objekten auftritt, sollte es funktionieren. –

+0

@qstarin oops, ja, guter Punkt. – Rup

+0

re # 2, Durch Einfügen einer .ToList() vor der Auswahl/Projektion (oder wo immer erforderlich) wird die Evaluierung von IQueryable erzwungen und die DB-Objekte geladen. –

1

Wenn Sie es als IQueryable halten möchten, können Sie dies tun:

 public IQueryable<Event> FindByLocation(float latitude, float longitude) 
     { 

      return from ev in GetAllEvents() 
        join i in db.NearestEvents(latitude, longitude) 
        on ev.ID equals i.ID 
        order by i.Distance 
        select ev; 
     } 

Solange die Methode GetAllEvents() auch IQueryable zurückgibt.

EDIT: Ich habe jetzt tatsächlich ausprobiert unter Rup Vorschlag, und Sie sollten eine IQueryable der Lage sein, ohne Berufung auf den DB-Aufruf in dieser Methode zurückzukehren. Beispiel:

 public IQueryable<EventDistance> FindByLocation(float latitude, float longitude) 
     { 
       return from ev in GetAllEvents() 
        join i in db.NearestEvents(latitude, longitude) 
        on ev.ID equals i.ID 
        orderby i.Distance 
        select new EventDistance 
        { 
         Event = ev, 
         Distance = i.Distance 
        }; 
     } 

Die EventDistance-Klasse muss nicht zugeordnet werden.

+0

Aber dann haben Sie die Eigenschaft i.Distance verloren - in seinem Beispiel speichert er diese in das Ereignisobjekt, um zurückzukehren. – Rup

+0

Woops ... ja, du hast so recht :) – asgerhallas

+2

Ich fange an zu glauben, dass die beste Antwort darin bestünde, deine Methode so zu modifizieren, dass du neue EventDistance() {TheEvent = ev, Distance = i.Distance} 'und return 'IQueryable '- würde das funktionieren? Ich bin verdächtig, es wäre nicht, da es kein Objekt ist, von dem die Datenschicht weiß - obwohl es etwas ist, für das es ein Rezept zum Mapping gibt. Ich bin jetzt richtig verwirrt. – Rup

1

Konnten Sie etwas so tun?

public IQueryable<Event> FindByLocation(float latitude, float longitude) 
    { 

     var eventsList = from ev in GetAllEvents() 
         join i in db.NearestEvents(latitude, longitude) 
         on ev.ID equals i.ID 
         select new Event { ID = ev.ID, Distance = i.Distance }; 


     return eventsList.OrderBy(e => e.Distance).AsQueryable(); 
    }