2009-04-04 5 views
0

Ich habe gerade angefangen zu lernen, wie man das Entity Framework benutzt, um ein sehr einfaches C# Netzwerk-Überwachungsprogramm zu schreiben - das ist eine Lernübung, um zu versuchen und nach Hause zu fahren Ich habe nur ungefähr bis heute gelesen. Ich bin auch neu in C# und LINQ (nur um die Dinge weiter zu komplizieren.)Eine Anfänger Entity Framework Abfrage um ein WinForms ListView zu füllen

Ich glaube, ich habe das Datenmodell geeignet normalisiert, aber ich kann falsch liegen. Visual Studio generiert ein konzeptionelles Modell, das OK aussieht. Ich habe die Assoziationen und EntitySets wo nötig pluralisiert, aber ich habe Schwierigkeiten, etwas zu tun, was ich für eine ziemlich einfache Abfrage/Projektion auf die Daten halte.

Die Datenbank enthält drei Tabellen:

[Server] - A server defined by the user that should be pinged. 
ServerID - primary key 
HostAddress - IP or hostname 

[Result] - A result containing data about the last server test 
ResultID - primary key 
ServerID - foreign key on [Server].[ServerID] 
StateID  - an integer used to lookup one of 3 possible Server states 
TimeStamp - Time stamp of last ping 

[State]  - A lookup table containing an integer -> string mapping. 
StateID  - a unique key 
StateLabel - human-readable string like "unreachable" or "OK" or "timeout" 

ich manuell die Datenbank mit ein paar einfachen Einträge bevölkert haben - gerade genug, um mir etwas zu arbeiten.

Zunächst möchte ich alle Ergebnisdaten in einem ListView auf einem WinForm präsentieren. Die ListView enthält die folgenden statischen Spalten:

Status | Serveradresse | Zuletzt überprüft

Theoretisch Daten der Listenansicht des durch die Projektion erzeugt werden muss über jede der drei Tabellen (?):.

  • Die Spalte „Status“ sollte den Menschen lesbaren [Status] Anzeige [ StateLabel] verbunden von [Ergebnis]. [StateID]
  • Die Spalte "Server Address" sollte [Server] anzeigen. [HostAddress] verknüpft von [Result]. [ServerID]
  • Die Spalte "Zuletzt überprüft" sollte anzeigen [ Ergebnis]. [Zeitstempel]

Da ich die Object Materialization und/oder Change-Tracking-Funktionen von ObjectServices nicht brauche, habe ich Recht, dass es effizienter/korrekter ist, Entity SQL/EntityClient und DbDataReader zu verwenden? Wenn ja, wie würde eine geeignete Entity SQL-Abfrage aussehen?

Für das, was es wert ist, habe ich versucht, LINQ to Entities und anonyme Typen in einem Verfahren unter Verwendung aber durch einen Mangel an Verständnis auf einem geeigneten Rückgabetyp wurde vereitelt:

var results = from r in _context.Result 
select new 
{ 
    State = (from s in _context.State 
     where s.StateId == r.StateId 
     select s.StateLabel), 
    r.ServerReference.Value.HostAddress, 
    r.TimeStamp 
}; 

return results.ToList(); // <- No can do. 

Vielen Dank für Ihre Hilfe!

Steve

Antwort

1

Nun, Sie nicht in der Lage sein, eine Liste von anonymen Typen zurückzukehren, wenn Sie sie zu object gegossen und haben die Signatur den Rückgabetyp als List<object> (oder einem entsprechenden Interface) definieren. Ihr anderes Problem ist, dass die Unterabfrage für State tatsächlich IQueryable anstelle eines einzelnen Eintrags zurückgibt (Sie können die Erweiterungsmethode First mit EF verwenden, um das erste übereinstimmende Element zu erhalten.) Wenn Sie die Fremdschlüsselbeziehung haben, sollte das Modell eingerichtet sein eine Navigationseigenschaft für den Staat, und Sie sollten in der Lage sein, die angehängte Eigenschaft anstelle einer Unterabfrage zu verwenden. Wenn Sie dies also als Methodenaufruf haben möchten, der eine Liste von Objekten zurückgibt, müssen Sie einen Typ erstellen, der die Transformation darstellt oder in ein Objekt umgewandelt wird. Andernfalls könnten Sie dies auf der Formularebene tun (dies hängt ganz von Ihren Anforderungen ab), wo Sie versuchen, die Liste zu binden.

public List<object> GetStuff() 
{ 
    var results = from r in _context.Result 
    select new 
    { 
     State = r.StateNavigationProperty.StateLabel, //If FK 
     State = _context.State.First(state => state.StateId == r.StateId), //If Not FK 
     HostAddress = r.ServerReference.Value.HostAddress, 
     TimeStamp = r.TimeStamp 
    }; 

    return results.Cast<object>().ToList(); 
} 

... 

myListView.DataSource = GetStuff(); 

Und wie ich schon sagte die andere Alternative ist es, eine Klasse für die Transformation oder die Liste bindet direkt an die Abfrage entweder zu erstellen.

public class SimpleStuff 
{ 
    public string State { get; set; } 
    public string HostAddress { get; set; } 
    public DateTime TimeStamp { get; set; } 
} 

Dann fügen Sie einfach die Klasse in die select new ala select new SimpleStuff und die Methodensignatur ändern, um die Klasse und entfernen Sie die Besetzung in der Rückkehr zu reflektieren.

+0

Danke Quintin, der Beispielcode hat mir sehr geholfen. – TheLearningCurve