views:

126

answers:

3

I am having a terrible time finding a solution to what I am sure is a simple problem.

I started an app with data in Lists of objects. It's pertinent objects used to look like this (very simplified):

class A {  
    int[] Nums;  
}

and

List<A> myListOfA;

I wanted to count occurrences of values in the member array over all the List.

I found this solution somehow:

var results  
    from a in myListOfA  
    from n in a.Nums  
    group n by n into g
    orderby g.Key
    select new{ number = g.Key, Occurences = g.Count}

int NumberOfValues = results.Count();

That worked well and I was able to generate the histogram I wanted from the query. Now I have converted to using an SQL database. The table I am using now looks like this:

MyTable {
  int Value1;
  int Value2;
  int Value3;
  int Value4;
  int Value5;
  int Value6;
}

I have a DataContext that maps to the DB.

I cannot figure out how to translate the previous LINQ statement to work with this. I have tried this:

MyDataContext myContext;

var results =
    from d in myContext.MyTable
    from n in new{ d.Value1, d.Value2, d.Value3, d.Value4, d.Value5, d.Value6 }
    group n by n into g
    orderby g.Key
    select new { number = g.Key, Occurences = g.Count() };

I have tried some variations on the constructed array like adding .AsQueryable() at the end - something I saw somewhere else. I have tried using group to create the array of values but nothing works. I am a relative newbie when it come to database languages. I just cannot find any clue anywhere on the web. Maybe I am not asking the right question. Any help is appreciated.

A: 

How about creating your int array on the fly?

var results =
    from d in myContext.MyTable
    from n in new  int[] { d.Value1, d.Value2, d.Value3, d.Value4, d.Value5, d.Value6 }
    group n by n into g
    orderby g.Key
    select new { number = g.Key, Occurences = g.Count() };
Aviad P.
I tried that - I get a NotSupportedException that says Constructed arrays are only supported for 'Contains'What ever that means.
Eric
A: 

In a relational database, such as SQL Server, collections are represented as tables. So you should actually have two tables - Samples and Values. The Keys table would represent a single "A" object, while the Values table would represent each element in A.Nums, with a foreign key pointing to the one of the records in the Samples table. LINQ to SQL 's O/R mapper will then create a "Values" property for each Sample object, which contains a queryable collection of the attached Values. You would then use the following query:

var results = 
    from sample in myContext.Samples
    from value in sample.Values
    group value by value into values
    orderby values.Key
    select new { Value = values.Key, Frequency = values.Count() };
Allon Guralnek
OK. Interesting. I am a little skeptical about a solution that requires a very particular organization of tables to make a language work. I would think the spirit of LINQ lies in Aviad's answer. I wish I could get that working. But out of curiousity is this attachment created in the process of creating the SQL Tables? Are you talking about a column in Samples that joins to the Values tavle? I would think there would have to be a join clause in there.
Eric
When you write a LINQ to SQL query, it is translated into a SQL query and sent to the server. SQL was created to work with relation databases. By creating a table with multiple fields you were in fact creating a flat database, which SQL is unable to reason with, even though LINQ can (but cannot translate it to SQL).
Allon Guralnek
When there are two tables that are linked together by a one-to-many relationship (via a foreign key), the O/R Mapper in VS2008 usually creates a link between them (if it doesn't you can create it manually), which manifests as a property on the "one" object that is a collection of the "many" objects that are linked to it (this property is lazy-loaded). So for each Sample object you would have a Values property that is a collection which contains all the values linked to that sample.
Allon Guralnek
Also, if you plan on just using ALL the values, and never filter which samples you want to use, then you can just select all records from the Values table and not go through the Samples table. (These character limits on comments is driving me crazy)Have a look at: http://msdn.microsoft.com/en-us/library/bb386951.aspx
Allon Guralnek
+1  A: 

I received help on a microsoft site. The problem is mixing LINQ to SQL with LINQ to Objects.

This is how the query should be stated:

var results = 
    from d in MyContext.MyTable.AsEnumerable()
    from n in new[]{d.Value1, d.Value2, d.Value3, d.Value4, d.Value5, d.Value6}
    group n by n into g
    orderby g.Key
    select new {number = g.Key, Occureneces = g.Count()};

Works like a charm.

Eric
But this does the grouping and sorting on the client-side, which defeats the purpose of LINQ to SQL. This also transfers the entire data of the table to the client, instead of just the results - not a good solution with a data set of any reasonable size.
Allon Guralnek
Sorry, but I really think you don't understand the purpose of LINQ (of any flavor) at all. the bottom line is this is exactly what I need for what I'm doing. There is no server-client architecture at all. It is all on one machine working with a local database.
Eric