J'ai une fonction où j'obtiens une liste d'identifiants et je dois retourner la liste correspondant à une description associée à l'identifiant. Par exemple.:
public class CodeData
{
string CodeId {get; set;}
string Description {get; set;}
}
public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
//Given the list of institution codes, return a list of CodeData
//having the given CodeIds
}
Donc, si je créais moi-même le SQL pour cela, je ferais simplement quelque chose comme ceci (où la clause in contient toutes les valeurs de l'argument codeIds):
Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')
Dans Linq to Sql, je n'arrive pas à trouver l'équivalent de la clause "IN". Le meilleur que j'ai trouvé jusqu'à présent (qui ne fonctionne pas) est:
var foo = from codeData in channel.AsQueryable<CodeData>()
where codeData.CodeId == "1" || codeData.CodeId == "2"
select codeData;
Le problème étant que je ne peux pas générer dynamiquement une liste de clauses "OR" pour linq to sql, car elles sont définies au moment de la compilation.
Comment peut-on accomplir une clause where qui vérifie qu'une colonne est dans une liste dynamique de valeurs en utilisant Linq to Sql?
Utilisation
where list.Contains(item.Property)
Ou dans votre cas:
var foo = from codeData in channel.AsQueryable<CodeData>()
where codeIDs.Contains(codeData.CodeId)
select codeData;
Mais vous pourriez aussi bien faire cela en notation à points:
var foo = channel.AsQueryable<CodeData>()
.Where(codeData => codeIDs.Contains(codeData.CodeId));
Vous pouvez aussi utiliser:
List<int> codes = new List<int>();
codes.add(1);
codes.add(2);
var foo = from codeData in channel.AsQueryable<CodeData>()
where codes.Any(code => codeData.CodeID.Equals(code))
select codeData;
J'avais utilisé la méthode dans la réponse de Jon Skeet, mais une autre méthode m'est venue en utilisant Concat
. La méthode Concat
a légèrement mieux performé dans un test limité, mais c’est un casse-tête et je vais probablement rester fidèle à Contains
, ou peut-être que j’écrirai une méthode auxiliaire pour le faire pour moi. De toute façon, voici une autre option si quelqu'un est intéressé:
// Given an array of id's
var ids = new Guid[] { ... };
// and a DataContext
var dc = new MyDataContext();
// start the queryable
var query = (
from thing in dc.Things
where thing.Id == ids[ 0 ]
select thing
);
// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
// select that thing and concat to queryable
query.Concat(
from thing in dc.Things
where thing.Id == ids[ i ]
select thing
);
}
Ce n'était pas à distance scientifique. J'imagine que votre structure de base de données et le nombre d'identifiants impliqués dans la liste auraient un impact significatif.
J'ai mis en place un test dans lequel j'ai effectué 100 essais, chacun des Concat
et Contains
, dans lequel chaque essai impliquait la sélection de 25 lignes spécifiées par une liste aléatoire de clés primaires. Je l'ai exécuté environ une douzaine de fois, et la plupart du temps, la méthode Concat
est 5 à 10% plus rapide, bien qu'une fois, la méthode Contains
ait été remportée par un petit gagnant.
var filterTransNos = (from so in db.SalesOrderDetails
where ItemDescription.Contains(ItemDescription)
select new { so.TransNo }).AsEnumerable();
listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();