2013-05-16 1 views
8

Ich versuche OData in WebApi zu implementieren. Ich verwende das Repository-Muster und EF5 (im Backend), das immer noch mit allen Beispielen übereinstimmt, die ich gefunden habe. Hier ist, wo etwas wackelig wird. Ich versuche, die EF-generierten Klassen hinter Modellen zu verstecken, die mit AutoMapper im Controller gemappt werden. Die Beispiele, die ich gesehen habe, scheinen zurückzukehren, was auch immer aus dem RepoImplementieren von OData mit WebApi und zugeordneten Modellen

Ich möchte nicht die OData-Parameter (auf die Ergebnisse, die zugeordnet wurden) im Controller, sondern im Repository, um den Wert von verzögerten erhalten Ausführung. Ich kann den ODataCriteria in das Repository übergeben, aber wenn ich versuche, Appy, erhalte ich einen Fehler, weil es scheint, dass die Optionen/Ergebnisse in das IQueryable < Model> von der Präsentationsschicht nicht IQueryable < EF_Class> eingegeben werden.

Ich sah jemanden anderes in einem anderen Beitrag, aber es war ein kleiner Teil des Beitrags und es schien nicht zu helfen.

Hat sich noch jemand damit beschäftigt? Ich möchte die EF-Klassen wirklich nicht veröffentlichen. Oh, ich benutze zuerst DB.

Vielen Dank im Voraus ...

Antwort

0

Hier ist ein Code, der Ihre Anforderung demonstriert.

das Ergebnis müssen Sie sicherstellen Um das zu erreichen, um, dass die Abfrage (mit ToList()) ausgeführt wurde. Die effizienteste Methode ist das Hinzufügen von Paging (Bonus) und das Zurückgeben eines Objekts PageResult<>.

public PageResult<WebPoco> Get(ODataQueryOptions<WebPoco> queryOptions) 
{ 
    var data2 = DatabaseData(); 

    //Create a set of ODataQueryOptions for the internal class 
    ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
    modelBuilder.EntitySet<DatabasePoco>("DatabasePoco"); 
    var context = new ODataQueryContext(
     modelBuilder.GetEdmModel(), typeof(DatabasePoco)); 
    var newOptions = new ODataQueryOptions<DatabasePoco>(context, Request); 

    var t = new ODataValidationSettings() { MaxTop = 25 }; 
    var s = new ODataQuerySettings() { PageSize = 25 }; 
    newOptions.Validate(t); 
    IEnumerable<DatabasePoco> results = 
     (IEnumerable<DatabasePoco>)newOptions.ApplyTo(data2, s); 

    int skip = newOptions.Skip == null ? 0 : newOptions.Skip.Value; 
    int take = newOptions.Top == null ? 25 : newOptions.Top.Value; 

    List<DatabasePoco> internalResults = results.Skip(skip).Take(take).ToList(); 

    // map from DatabasePoco to WebPoco here: 
    List<WebPoco> webResults; 

    PageResult<WebPoco> page = 
     new PageResult<WebPoco>(
      webResults, Request.GetNextPageLink(), Request.GetInlineCount()); 

    return page; 
} 

Hier ist die Verwendung von Aussagen

using System.Web.Http; 
using System.Web.Http.OData; 
using System.Web.Http.OData.Builder; 
using System.Web.Http.OData.Query; 

Testklassen

public class WebPoco 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public string type { get; set; } 
} 

public class DatabasePoco 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public string type { get; set; } 
} 

und einige Daten zur Prüfung

private IQueryable<DatabasePoco> DatabaseData() 
{ 
    return (
     new DatabasePoco[] { 
      new DatabasePoco() { id = 1, name = "one", type = "a" }, 
      new DatabasePoco() { id = 2, name = "two", type = "b" }, 
      new DatabasePoco() { id = 3, name = "three", type = "c" }, 
      new DatabasePoco() { id = 4, name = "four", type = "d" }, 
      new DatabasePoco() { id = 5, name = "five", type = "e" }, 
      new DatabasePoco() { id = 6, name = "six", type = "f" }, 
      new DatabasePoco() { id = 7, name = "seven", type = "g" }, 
      new DatabasePoco() { id = 8, name = "eight", type = "h" }, 
      new DatabasePoco() { id = 9, name = "nine", type = "i" } 
     }) 
     .AsQueryable(); 
} 
+0

Ich mag diesen Ansatz, leider arbeite ich mit einer Legacy-db und bekomme den folgenden Fehler ... Der komplexe Typ x bezieht sich auf den Entitätstyp Y durch die Eigenschaft Z. Ich kann nicht finden, irgendetwas darüber auf Google, ich kann nur annehmen, dass es das Potenzial eines zirkulären ref oder etwas anzeigt ... – Lenny

+0

@Lenny - Die 'ToList()' sollte die db aus der Gleichung entfernen. Aber mit EF-Mappings wer weiß ?! Es könnte eine beliebige Anzahl von Dingen sein, die mit Proxies, Lazy Loading etc. zu tun haben. Welche Zeile schlägt fehl? – qujck

+0

überprüfen Sie, ob dies hilfreich aussieht ... http://stackoverflow.com/questions/15438195/odata-exception-the-complex-type-webtools-order-refers-to-the-entity-type-web Vielen Dank – Lenny

0

Wenn die Abfragbare Sie über ein dbContext.dbSet.Select (x => neues Modell {Id = x.Id}) zurückzukehren Mechanismus statt AutoMapper. Dann kann die Anwendung von Bedingungen auf Queryable vom EF LINQ-Provider automatisch übersetzt und ausgewertet werden. Andernfalls müssen Sie einen benutzerdefinierten LINQ-Provider schreiben, der die Ausdrücke von Ausdrucken auf Basis von Modelleigenschaften zu Ausdrücken aus EF_Class-Eigenschaften ändert.

+1

Hmm, nicht zu lieben. Wenn ich die EF-Klasse verwende, dann kann ich die ID-Eigenschaft (zusammen mit anderen IDs) nicht zugunsten einer Navigationseigenschaft verbergen, die das URI der Ressource ist. Die einzige Möglichkeit, die noch möglich ist, wäre eine hässliche partielle Klassenarbeit oder Änderungen an der t4-Vorlage, die die EF-Klasse generiert. Gehe ich falsch herum? Soll ich wirklich nur die EF-Klassen teilen? – Lenny