1

I am trying to use LINQ to SQL to query corresponding data based on the values in my array, but am having issues. I was reading these threads, but am not sure if they are actually what I'm trying to do, and if they are how to implement them:

LINQ equivalent of foreach for IEnumerable<T>

Linq style "For Each"

I have my Array of strings 'lines[]', how can I run the following query for each entry, and store the results in a way that allows me to output them in a coherent manner. Again here is a sample of my array: Example: Z1234 Z2345 ZAF38383

//some non working code
List<string> results = new List<string>();

var thisQuery = from c in myContext.SpecificTable
where c.itemNumber == (foreach (string i in lines))
select c;

foreach (var result in thisQuery)
{
    results.Add(result);
}

The list creation is fine, and the write to the list would be ok too I think, but I can't figure out how to run the query for each item int he Array?

Each entry in my array begins with Z and then will contain any arrangement of alpha-numeric characters if it matters. Example: Z3333

Each entry in the array corresponds to an entry in a table in my database 'SpecificTable'. I want to return everything pertaining to this value, in that table, so I can then output the specifics of that data.

Example: I want to begin by quering Z1234, and when Z1234 is found in 'SpecificTable' I want to be able to output the various details like this:

foreach (var res in thisQuery)
{
   //each result from the query (total of 3 from the example) will now show their Description in a messagebox.
   MessageBox.Show("Description:" + res.Description.ToString());
 }

By using the loop I hope to be able to create a list of all results based on the initial array, and output their corresponding various values such as the 'Description'.

If this is still not enough info, please let me know what I can provide to be more clear.

Community
  • 1
  • 1
Fuzz Evans
  • 2,893
  • 11
  • 44
  • 63
  • 2
    `foreach (var result in thisQuery) { results.Add(result); }` can be shortened to `results = thisQuery.ToList();` – nothrow Sep 20 '13 at 23:01

2 Answers2

1

Try:

This will loop the rows in myContext.SpecificTable and creates an innerloop to check if there is a match within the lines.

var thisQuery = from c in myContext.SpecificTable
                from i in lines
                where c.itemNumber == i
                select c;

or this:

This will do the same, only the second 'iterator' is done within the contains.

var thisQuery = from c in myContext.SpecificTable
                where  lines.Contains(c.itemNumber)
                select c;

I think it's best to put the db query in the outerloop, because you don't want a 'tablescan' for each item in lines.

So it will do a 'tablescan' only ones, and try to find a match in the lines.

I think it will speed up if you try something like this:

var linesHashSet = new HashSet<string>(lines);

var thisQuery = from c in myContext.SpecificTable
                where  linesHashSet.Contains(c.itemNumber)
                select c;

Here it will use in the second iteration a hashset (indexed list)


Update:

It is possible to iterate the rows clientside, like this:

var thisQuery = from c in myContext.SpecificTable.ToArray()
                where  lines.Contains(c.itemNumber)
                select c;

But this will have a performance inpact. I suggest you try the middle one.

Jeroen van Langen
  • 21,446
  • 3
  • 42
  • 57
  • When I tried your first query, it returned the following error:Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator. I don't really know what that's about. I got the last example to at least not error when I used the line 'where linesHashSet.ToList().Contains.... but my later call to view the contents of thisQuery is not yielding any results which I imagine means my query isn't actually selecting anything? – Fuzz Evans Sep 20 '13 at 23:45
  • `Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator.` Means it want to create one query for the whole linq statement, but it cannot translate the `from i in lines` to an sql statement. I suggest you use the middle one. Is it possible to monitor what sql statement is generated? I'll add something to my answer. – Jeroen van Langen Sep 20 '13 at 23:49
  • About the empty results, i don't know how the data is looks like, so i cannot predict the results. – Jeroen van Langen Sep 20 '13 at 23:52
  • The second query is the common approach (if I understood the OP well, the question is not too clear). Converting to a hashset first is of no use because the `lines` array is only enumerated once when the query provider generates an `IN` clause. @FuzzEvans, If this does not produce the right results you need to give more details about input and expected output. – Gert Arnold Sep 21 '13 at 20:04
  • The HashSet has only use, if the query is executed client side. (IEnemerable instead of IQueryable) – Jeroen van Langen Sep 21 '13 at 21:02
  • See original post for updated info. Hopefully this contains enough to explain what type of issues I'm running into. – Fuzz Evans Sep 23 '13 at 15:35
1

Not sure if I understand your question correctly, but you want to join the entries in SpecificTable with the "lines" array, and output the results as a list?

var results = myContext.SpecificTable.Select(c => lines.Contains(c.ItemNumber)).ToList();
foreach(var result in results)
{
    Console.WriteLine(string.format("{0}:{1}", "Description", result.Description));
}

In case you want specific properties only, you can return a list of anonymous objects.

var results = myContext.SpecificTable.Where(c => lines.Contains(c.ItemNumber)).Select(c => new {c.ItemNumber, c.Description}).ToList();
foreach(var result in results)
{
    Console.WriteLine(string.format("{0}:{1}", "Description", result.Description));
}
tranceporter
  • 2,241
  • 1
  • 21
  • 23
  • Where the 'results' are already put into a list, doesn't this make it unable to process the last call for 'result.Description'? Trying it in my project doesn't recognize result.Description, and I'm wondering if that's why? – Fuzz Evans Sep 23 '13 at 15:53
  • The 'results' will be of type IEnumerable> I guess. The easiest way to find out is to put a breakpoint, and find the return type of the Select query. Essentially, if the type of individual elements is not what you want, you can extract specific properties. Does you 'SpecificTable' object have a Description property? – tranceporter Sep 23 '13 at 15:57