2010-01-04 8 views
1

Je passe un moment difficile à trouver une solution à ce qui, j'en suis sûr, est un problème simple. J'ai commencé une application avec des données dans des listes d'objets.Comptabiliser les occurrences de valeurs sur plusieurs colonnes

Il est des objets pertinents utilisés pour ressembler à ceci (très simplifié):

class A { 
    int[] Nums; 
} 

et

List<A> myListOfA; 

que je voulais compter les occurrences de valeurs dans le tableau des membres de toute la liste.

Je trouve cette solution en quelque sorte:

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(); 

Cela a bien fonctionné et j'ai pu générer l'histogramme je voulais de la requête. Maintenant, j'ai converti à l'aide d'une base de données SQL. La table que j'utilise ressemble maintenant à ceci:

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

J'ai un DataContext qui mappe sur le DB.

Je ne peux pas comprendre comment traduire l'instruction LINQ précédente pour travailler avec cela. Je l'ai essayé:

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() }; 

J'ai essayé quelques variations sur le tableau construit comme l'ajout .AsQueryable() à la fin - quelque chose que j'ai vu ailleurs. J'ai essayé d'utiliser le groupe pour créer le tableau de valeurs mais rien ne fonctionne. Je suis un débutant relatif quand il s'agit de langues de base de données. Je ne trouve tout simplement aucune idée sur le web. Peut-être que je ne pose pas la bonne question. Toute aide est appréciée.

Répondre

0

Pourquoi ne pas créer votre tableau int à la volée?

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() }; 
+0

J'ai essayé - je reçois un NotSupportedException qui dit tableaux ne sont pris en charge Construits pour « Contient » Quel que cela signifie. – Eric

0

Dans une base de données relationnelle, telle que SQL Server, les collections sont représentées sous forme de tables. Vous devriez donc avoir deux tables: des exemples et des valeurs. La table Keys représenterait un seul objet "A", tandis que la table Values ​​représenterait chaque élément dans A.Nums, avec une clé étrangère pointant vers l'un des enregistrements de la table Samples. Le mappeur O/R de LINQ to SQL créera alors une propriété "Valeurs" pour chaque objet Sample, qui contient une collection interrogeable des valeurs attachées. Vous devez ensuite utiliser la requête suivante:

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() }; 
+0

OK. Intéressant.Je suis un peu sceptique quant à une solution qui nécessite une organisation très particulière des tables pour faire fonctionner une langue. Je pense que l'esprit de LINQ réside dans la réponse d'Aviad. J'aimerais pouvoir le faire fonctionner. Mais par curiosité est cette pièce jointe créée dans le processus de création des tables SQL? Parlez-vous d'une colonne dans Samples qui se joint au tavle Values? Je pense qu'il devrait y avoir une clause de participation. – Eric

+0

Lorsque vous écrivez une requête LINQ to SQL, elle est traduite en requête SQL et envoyée au serveur. SQL a été créé pour fonctionner avec des bases de données relationnelles. En créant une table avec plusieurs champs, vous étiez en train de créer une base de données plate, que SQL est incapable de raisonner, même si LINQ le peut (mais ne peut pas le traduire en SQL). –

+0

Quand il y a deux tables qui sont reliées entre elles par une relation un à plusieurs (via une clé étrangère), l'O/R Mapper dans VS2008 crée généralement un lien entre eux (si elle ne vous pouvez créer manuellement) , qui se manifeste comme une propriété sur l'objet "un" qui est une collection des "nombreux" objets qui lui sont liés (cette propriété est paresseuse). Ainsi, pour chaque objet Sample, vous aurez une propriété Values ​​qui est une collection qui contient toutes les valeurs liées à cet échantillon. –

1

J'ai reçu de l'aide sur un site Microsoft. Le problème est de mélanger LINQ à SQL avec LINQ to Objects.

Voici comment convient de préciser la requête:

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()}; 

fonctionne comme un charme.

+1

Mais cela ne le regroupement et le tri sur le côté client , ce qui va à l'encontre du but de LINQ to SQL. Cela transfère également toutes les données de la table au client, au lieu de seulement les résultats - pas une bonne solution avec un ensemble de données de toute taille raisonnable. –

+0

Désolé, mais je pense vraiment que vous ne comprenez pas le but de LINQ (de toute saveur) du tout. l'essentiel est que c'est exactement ce dont j'ai besoin pour ce que je fais. Il n'y a pas du tout d'architecture serveur-client. C'est tout sur une machine fonctionnant avec une base de données locale. – Eric

0

Si vous souhaitez utiliser LINQ to SQL, vous pouvez essayer ce "hack" que j'ai récemment découvert. Ce n'est pas le plus joli des codes les plus propres, mais au moins vous n'aurez pas à revenir à l'utilisation de LINQ to Objects.

var query = 
    from d in MyContext.MyTable 
    let v1 = MyContext.MyTable.Where(dd => dd.ID == d.ID).Select(dd => dd.Value1) 
    let v2 = MyContext.MyTable.Where(dd => dd.ID == d.ID).Select(dd => dd.Value2) 
    // ... 
    let v6 = MyContext.MyTable.Where(dd => dd.ID == d.ID).Select(dd => dd.Value6) 
    from n in v1.Concat(v2).Concat(v3).Concat(v4).Concat(v5).Concat(v6) 
    group 1 by n into g 
    orderby g.Key 
    select new 
    { 
     number = g.Key, 
     Occureneces = g.Count(), 
    }; 
Questions connexes