In Teil 1 haben wir, mit Hilfe des Entity Frameworks, folgendes Entity Data Model erzeugt.
Ausgehend von folgendem Entity Data Model, soll nun eine Liste von abonnierten Feeds eines Users via ADO.NET Dataservices aus der Datenbank abgerufen werden.
Dem ASP.NET Web Host Projekt mittels “Add->New Item” ein neues ADO.NET Data Service hinzufügen.
Dadurch wird ein Service Gerüst erzeugt, welches von DataService<T> erbt. Nun muss nur noch als generischer parameter der Typ des, in Teil 1 erzeugen, Entity Data Model angegeben werden. In diesem Fall ist lautet der Typ ‘SilverFeedDbEntities’ .
1: public class SilverFeedDataService : DataService<SilverFeedDbEntities>
2: {
3: public static void InitializeService(IDataServiceConfiguration config)
4: {
5: config.SetEntitySetAccessRule("*", EntitySetRights.All);
6: }
7: }
In der statischen InitializeService() Methode werden mittels SetEntitySetAccessRule(string name, EntitySetRights rights) die Zugriffsrechte für einzelne Entitäten oder für das ganze Modell gesetzt werden. Im obigen Beispiel wird mit * und EntityAccessRight.All Vollzugriff (CRUD) auf alle Entitäten des Modells gewährt, was in der Realität sicherheitstechnisch wahrscheinlich etwas zu locker wäre.
Sollen alle Operationen auf ‘Feed’ erlaubt sein, aber auf der Entität ‘User’ nur das Lesen, würde das so aussehen.
1: public class SilverFeedDataService : DataService<SilverFeedDbEntities>
2: {
3: public static void InitializeService(IDataServiceConfiguration config)
4: {
5: config.SetEntitySetAccessRule("Feed", EntitySetRights.All);
6: config.SetEntitySetAccessRule("User", EntitySetRights.AllRead);
7: }
8: }
Jetzt wollen wir den Service natürlich in der Silverlight Applikation verwenden und Steuerelemente an die Daten binden. Dazu als Erstes im Silverlight Projekt mit Rechtsklick und ‘Add Service Reference ‘ eine Referenz auf das erstellte ADO.NET Dataservice hinzufügen. Im Wizard einfach auf ‘Discover klicken, den entsprechenden Service auswählen und noch einen sinnvollen Klassennamen wählen.

Um die abonnierten Feeds eines Users anzuzeigen, verwenden wir ein Page View Model, das die Daten abruft und dem Silverlight Control zur Datenbindung zur Verfügung stellt.
1: public class FeedsViewModel : INotifyPropertyChanged
2: {
3: private IEnumerable<Feed> _feeds;
4: public IEnumerable<Feed> Feeds
5: {
6: get { return _feeds; }
7: set
8: {
9: if (value.Equals(_feeds)) return;
10: _feeds = value;
11: OnPropertyChanged("Feeds");
12: }
13: }
14:
15: #region INotifyPropertyChanged Members
16:
17: public event PropertyChangedEventHandler PropertyChanged;
18:
19: protected void OnPropertyChanged(string propertyName)
20: {
21:
22: if (PropertyChanged != null)
23: PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
24:
25: }
26:
27: #endregion
28:
29: public FeedsViewModel(string username)
30: {
31: LoadFeeds(username);
32: }
33:
34: private void LoadFeeds(string username)
35: {
36: var userFeedsQuery = ((DataServiceQuery<User>) from user in Context.Current.UserSet
37: where user.UserName == username
38: select user).Expand("Feeds");
39:
40: userFeedsQuery.BeginExecute((asyncResult)
41: => { Feeds = userFeedsQuery.EndExecute(asyncResult)
42: .Single().Feeds; },userFeedsQuery);
43:
44: }
45:
46:
47: }
Damit ein Silverlight Control auf Änderungen an gebundenen Eigenschaften reagiert, muss unser Page View Model das Interface ‘INotifyPropertyChanged’ implementieren.
Die Eigenschaft Feeds enthält die via ADO.NET Dataservice geladenen Feeds des Users. Im Setter wird das PropertyChanged Ereignis zum aktualisieren der UI ausgelöst.
Der interessante Teil ist das Laden der Daten. Zuerst wird mittels LINQ die entsprechende Abfrage erstellt und nach DataServiceQuery<User> gecasted. Der Aufruf von Expand(“Feeds”) bewirkt, dass für jeden selektierten User auch gleich die Feeds mitgeladen werden. Feeds bezieht sich dabei auf die Navigation Property von User –> Feeds die automatisch im Entity Data Model für uns erzeugt wurde, da in unserem relationalen Schema eine 1..n Beziehung zwischen den beiden besteht.
Die eigentliche Abfrage via Dataservice ist asynchron und wird mittels BeginExecute angestossen. In der Lambda Expression wird die Eigenschaft Feeds als Resultat von EndExecute gesetzt. Da wir nur genau einen User selektieren wird hier gleich Single() aufgerufen damit wir über die Eigenschaft ‘Feeds’ der Entität ‘User’ direkt die Feeds referenzieren können.
Was nun noch zu tun ist, ist die gewonnenen Daten an ein Control zu binden. Am schnellsten geht das mit einem Silverlight DataGrid.
<data:DataGrid x:Name="feedsGrid" AutoGenerateColumns="True" ItemsSource="{Binding Feeds}" />
Im Konstruktor unsere Silverlight Page erzeugen wir eine neue Instanz des Page View Models (Ich habe die Klasse FeedViewModel genannt) und setzten den DataContext auf diese neue Instanz…fertig!
DataContext = new ViewModels.FeedsViewModel("Andi");
Die Daten werden asynchron über den ADO.NET DataService geladen und das Event OnPropertyChanged sorgt dafür, dass sich die UI bei Änderungen sofort aktualisiert.
Links:
Datenbindung in XAML
Silverlight Applikationen mit LINQ und ADO.NET Dataservices
ADO.NET Dataservices Framework (MSDN)