V minulém dílu seriálu o ADO.NET Data Services jsme se podívali na základní možností dotazování navigace a filtrování. Dnes u tohoto tématu ještě zůstaneme podíváme se na některé pokročilé možnosti, které můžeme při práci s ADO.NET Data Services využít.
reklama
V minulém dílu seriálu o ADO.NET Data Services jsme se podívali na základní možností dotazování navigace a filtrování. Dnes u tohoto tématu ještě zůstaneme podíváme se na některé pokročilé možnosti, které můžeme při práci s ADO.NET Data Services využít.
Jednoduchou možností je předpřipravení výsledku na základě nějaké podmínky, takže dotazující strana se může odstínit od některých základních filtrů – typicky např. aktivní uživatelé, nevyřízené objednávky atp. Pro tento účel jsou připraveny tzv. Service Operations metody. Abychom si fungování ukázali, budeme nejprve provádět jednoduchý filtr na základě atributu entity b a poté tuto metodu rozšíříme.
První co je třeba udělat, je povolení přístupu k naší metodě. Přidáme tedy do InitializeService řádek:
config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
Přesnější vysvětlení omezení přístupu opět nechávám na závěr seriálu. Poté již stačí vytvořit instanční veřejnou (public) metodu, vracející IQueryable<T> (případně IEnumerable<T>, nicméně v tomto případě nelze s výsledkem dále pracovat pomocí operátorů představených v minulém díle) a odekorovanou atributem [WebGet].
[WebGet]
public IQueryable<MyModel.b> MyServiceOperation()
{
return this.CurrentDataSource.b
.Where(b => b.y != "rrr")
.OrderByDescending(b => b.y);
}
Pomocí this.CurrentDataSource máme přístup k modelu a můžeme provádět libovolné dotazovací operace s množinou/množinami entit. Výsledek je potom dostupný na URI http://localhost:2634/MyDataService.svc/MyServiceOperation.
Jak lze lehce nahlédnout, bez možnosti parametrizace metody by toto řešení bylo polovičaté, a proto jsou samozřejmě podporovány i metody s parametry. Přidejme proto dva parametry a upravme lehce metodu, např.:
[WebGet]
public IQueryable<MyModel.b> MyServiceOperation(string y1, string y2)
{
return this.CurrentDataSource.b
.Where(b => b.y == y1 || b.y == y2)
.OrderByDescending(b => b.y);
}
Výsledkem této modifikace je možnost předat do metody parametry, které můžeme dále použít v dotazu (nejčastěji asi omezení hledaní), a na výsledek se dotazovat pomocí URI http://localhost:2634/MyDataService.svc/MyServiceOperation?y1='sest'&y2='tri'. Jak již bylo zmíněno, můžeme aplikovat i další standardní operátory, např.: http://localhost:2634/MyDataService.svc/MyServiceOperation?y1='sest'&y2='tri'&$filter=id gt 2.
Vrátíme-li se zpátky k atributu [WebGet], tak ten neříká nic jiného, než že na této metodě chceme povolit GET operace. Jeho kolegou je atribut [WebInvoke], který deklaruje dostupnost přes HTTP POST.
Samozřejmě tyto atributy nejsou jediné, které můžeme použít, minimálně další dva jsou užitečné. První z nich je [SingleResult], který deklaruje, že metoda vrací pouze jednu instanci (pokud vrátí více než jednu, bude výsledek obsahovat první a výjimku jako další „záznam“). Druhý, podle mne velmi užitečný, je [MimeType(string memberName, string mimeType)], který říká v jakém MIME typu je hodnota ($value) vracena a na jaký prvek třídy resp. entity se tento MIME type vztahuje. Pokud je definován přímo pro třídu typu DataService, uvádí se jako memberName název Service Operation metody. Tento atribut je velmi účelný pokud Service Operation metoda vrací např. obrázek a chcete jej poslat rovnou do browseru na daném URI.
Upravíme-li si metodu, aby vracela výsledek např. v HTML:
[MimeType("MyServiceOperation", "text/html")]
public class MyDataService : DataService<MyModel.MyEntities>
{
[WebGet]
[SingleResult]
public IQueryable MyServiceOperation()
{
string[] result = new string[] { string.Format("<html><body><h1>{0}</h1></body></html>", this.CurrentDataSource.b.Count().ToString()) };
return result.AsQueryable<string>();
}
...
}
Případně přímo s vrácením výsledku:
[WebGet]
[SingleResult]
public string MyServiceOperation()
{
return string.Format("<html><body><h1>{0}</h1></body></html>", this.CurrentDataSource.b.Count().ToString());
}
Stačí zavolat http://localhost:2634/MyDataService.svc/MyServiceOperation/$value a máme výstup přímo jako HTML, včetně odpovídající definice MIME typu v hlavičkách.
Dosud jsme se bavili pouze o dotazování v rámci Service Operation metod. Tyto však nemusí data pouze získávat, ale mohou je i modifikovat. Díky dostupnosti datového zdroje přes this.CurrentDataSource je možné provádět všechny CUD (Create, Update, Delete) operace.
public IQueryable<string> MyServiceOperation()
{
MyModel.b x = new MyModel.b();
x.y = "rrr";
this.CurrentDataSource.AddTob(x);
this.CurrentDataSource.SaveChanges();
string[] result = new string[] { string.Format("<html><body><h1>{0}</h1></body></html>", this.CurrentDataSource.b.Count().ToString()) };
return result.AsQueryable<string>();
}
Voláním výše uvedené metody se vždy založí nová entita typu b a číslo vrácené ve výsledku bude o jedna větší (smysluplnost, prosím, ponechme stranou).
Díky možnosti zakomponovat do metody (téměř) libovolnou logiku práce s daty, stávají se Service Operation metody velkým pomocníkem a vhodnou enkapsulací některých dotazů (resp. změn), které služba poskytuje světu. V příštím díle se podíváme na možnosti přímých změn dat.