web-dev-qa-db-fra.com

OData "ID dans la liste" requête

J'ai un service OData où j'essaie de filtrer par une liste d'identifiants; l'équivalent SQL serait quelque chose comme:

SELECT * FROM MyTable WHERE TableId IN (100, 200, 300, 400)

La propriété sur laquelle j'essaie de filtrer est typée Int32. J'ai essayé ce qui suit, ce qui me donne l'erreur "Ajouter" incompatible avec les types d'opérande "Edm.String" et "Edm.Int32" ":

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains("," + t.media_id + ",")

aussi bien que

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains("," + t.media_id.ToString() + ",")

et

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains("," + Convert.ToString(t.media_id) + ",")

et

string ids = ",100,200,300,400,";
from m in provider.Media where ids.Contains(string.Concat(",", t.media_id, ","))

Comme vous pouvez le constater, j'utilise actuellement LINQ pour interroger le service.

Existe-t-il un moyen de faire ce que j'essaie ou suis-je obligé de créer un filtre de texte et d'utiliser AddQueryOption, de parcourir la liste et d'ajouter manuellement des clauses "ou media_id eq 100"?

42
technophile

Avec OData 4.01 , l'instruction in est prise en charge comme suit:

http://Host/service/Products?$filter=Name in ('Milk', 'Cheese')
13
martinoss

Voir réponse acceptée, tout ce qui suit est destiné à OData v <4.01

essaye celui-là

 var ids = new [] { 100, 200, 300 } ;
 var res = from m in provider.Media 
           from id in ids 
           where m.media_id == id 
           select m;

il existe une description complète sur msdn on query DataServices. </ strike>

une autre approche serait 

var results = provider.Media
   .AddQueryOption("$filter", "media_id eq 100");

et comme OData ne prend pas en charge les instructions IN, vous obtiendrez une condition de filtre comme celle-ci.

.AddQueryOption("$filter", "(media_id eq 100) or (media_id eq 200 ) or ...");

que vous pouvez construire en utilisant loop ou linq Select et string.Join:

var ids = new [] { 100, 200, 300 };
var filter = string.Join(" or ", ids.Select(i=> $"(media_id eq {i})"));
var results = provider.Media.AddQueryOption("$filter", filter);

UPDATE: Il existe une opération de filtrage field=["a","b"], mais cela signifie quelque chose de différent. 

UPDATE2: Dans OData V4, il y a des expressions lambda any et all, associées au tableau littéral ["a", "b"], elles peuvent fonctionner comme in mais je n'ai pas été en mesure de donner un exemple d'utilisation utilisant le point de terminaison v4 à OData.org

33
vittore

En développant la réponse de vittore (dont la deuxième partie est la bonne réponse), j'ai écrit quelque chose de similaire au suivant pour un projet de démonstration:

var filterParams = ids.Select(id => string.Format("(media_id eq {0})", id));
var filter = string.Join(" or ", filterParams);
var results = provider.Media.AddQueryOption("$filter", filter).Execute().ToList();

Ce n'est pas élégant, et vous ne voudriez pas l'utiliser pour une longue liste d'identifiants (> ~ 60), mais ça fera l'affaire.

13
MCattle

En développant la suggestion de MCattle si nous avons besoin de plus de 50 ou 60 identifiants, il est conseillé de faire deux appels parallèles ou plus et de les ajouter à un dictionnaire simultané ou quelque chose de similaire lorsque nous obtenons des résultats du serveur. Bien que cela augmente le nombre d'appels au serveur, mais comme nous passons lentement vers l'environnement cloud, cela ne devrait pas être un gros problème à mon avis. 

0
Navap