2012-11-27 7 views
3

Je ne suis pas sûr de ce que je manque, mais je me suis débattu à celui-ci tout l'après-midi.Linq to Entities Sélectionnez Distinct

J'ai vue Sql Server d'entreprises qui ressemble à ceci:

CompanyId varchar(30) NOT NULL 
CompanyName varchar(100) NOT NULL 
CompanyPriority int NULL 
ConfigItem int NOT NULL 

avec des données qui ressemble un peu à ceci:

00001 | Company One | 99 | 123 
00001 | Company One | 99 | 456 
00001 | Company One | 99 | 789 
00002 | Company Two | 99 | 123 
00002 | Company Two | 99 | 456 

J'essaie d'obtenir une liste distincte de entreprises. La requête SQL Je veux exectute est

select distinct CompanyId, CompanyName,CompanyPriority from vwCompany 

qui me donne exactement les résultats que je veux ce qui serait

00001 | Company One | 99 
00002 | Company Two | 99 

Mais pour la vie de moi je ne peux pas trouver la requête LINQ qui entraîne ce sql, ou tout ce qui produit les mêmes résultats. Toutes les questions que j'ai trouvées utilisent le groupage qui fonctionne bien dans mes tests unitaires mais ne renvoie pas de résultats distincts lorsqu'il est exécuté sur une base de données réelle.

EDIT:

J'ai essayé quelques petites choses sur la base des réponses à ce jour.

Dim data = _miRepository.GetCompanies(). 
    Select(Function(c) New With { 
      .companyId = c.CompanyId, 
      .companyName = c.CompanyName, 
      .companyPriority = c.CompanyPriority 
     } 
     ).Distinct().ToList() 

génère le sql

SELECT 
1 AS [C1], 
[Extent1].[CompanyId] AS [CompanyId], 
[Extent1].[CompanyName] AS [CompanyName], 
[Extent1].[CompanyPriority] AS [CompanyPriority] 
FROM (SELECT 
     [vwCompany].[CompanyId] AS [CompanyId], 
     [vwCompany].[CompanyName] AS [CompanyName], 
     [vwCompany].[CompanyPriority] AS [CompanyPriority], 
     [vwCompany].[CiId] AS [CiId] 
     FROM [dbo].[vwCompany] AS [vwCompany]) AS [Extent1] 

qui n'a pas l'opérateur distinct dans du tout :(

Et oui, je le fais en VB.NET juste pour faire il est plus difficile de trouver de bons exemples: \

EDIT 2:

Je suis en train de se rapprocher de Eric Js rép er comme je peux en VB.

Dim data = (From c In _miRepository.GetCompanies() 
      Select New With {.companyId = c.CompanyId, 
          .companyName = c.CompanyName, 
          .companyPriority = c.CompanyPriority 
          } 
         ).Distinct().ToList() 

me donne

SELECT 
1 AS [C1], 
[Extent1].[CompanyId] AS [CompanyId], 
[Extent1].[CompanyName] AS [CompanyName], 
[Extent1].[CompanyPriority] AS [CompanyPriority] 
FROM (SELECT 
     [vwCompany].[CompanyId] AS [CompanyId], 
     [vwCompany].[CompanyName] AS [CompanyName], 
     [vwCompany].[CompanyPriority] AS [CompanyPriority], 
     [vwCompany].[CiId] AS [CiId] 
     FROM [dbo].[vwCompany] AS [vwCompany]) AS [Extent1] 

Encore aucun mot-clé distinct pour trouver :(

Peut-être qu'il ya une différence subtile dans VB.NET que je suis absent.

EDIT 3 :

Afin de progresser dans le reste de cette application, j'ai abandonné pour le mo ment et créé une nouvelle vue (vwDistinctCompanies) en utilisant l'instruction sql au début de la question.

Si quelqu'un parvient à faire fonctionner ceci dans VB.NET contre une vue Sql s'il vous plaît faites le moi savoir. Tout à fait pourquoi cela devrait être si difficile dans LINQ Je n'ai aucune idée :(

+0

Juste au cas où vous essayez encore, j'ai essayé plusieurs requêtes moi-même et les différents d'autres utilisateurs. Il semble que la réponse de @Eric J. me donne l'instruction SQL qui utilise le mot-clé 'DISTINCT'. Je ne sais pas comment traduire cela à VB comme je les ai couru à travers C# – Steven

+0

Merci d'avoir essayé. Je ne pouvais pas obtenir d'entre eux pour faire une requête distincte. Je ne sais pas si c'est parce que c'est en VB ou si c'est parce que c'est contre une vue plutôt qu'une table. – Nick

+0

Hey, j'ai couru d'autres questions. Regardez ma réponse éditée. J'espère que cela aide. – Steven

Répondre

2

Essayez d'utiliser .Distinct() à la fin de votre requête, par exemple.

(from r in ctx.MyTable where SomeCondition select r).Distinct(); 

http://msdn.microsoft.com/en-us/library/system.linq.enumerable.distinct.aspx

Si nécessaire, vous pouvez également fournir un IEqualityComparer. Cependant, pour utiliser IEqualityComparer, l'énumérable qui en résulte doit d'abord être matérialisé en utilisant. ToEnumerable(). Cela signifie que l'opération Distinct() est effectuée sur le client plutôt que sur le serveur de base de données.

http://msdn.microsoft.com/en-us/library/bb338049.aspx

Le IEqualityComparer vous permet de contrôler exactement quels documents sont traités comme égaux et donc pas distinct des autres dossiers.

Si vous voulez sélectionner un sous-ensemble de colonnes de votre table, changer

select r 

pour sélectionner un type anonyme comme ceci:

(from r in ctx.MyTable where SomeCondition 
    select new 
    { 
     CompanyId = r.CompanyId, 
     CompanyName = r.CompanyName, 
     CompanyPriority = r.CompanyPriority 
    } 
).Distinct(); 

ou si vous avez besoin d'un objet fortement typé (par exemple, parce que vous utilisez des vues fortement typées dans MVC:

public class CompanyModel 
{ 
    public int CompanyId { get; set; } 
    public string CompanyName { get; set; } 
    public int CompanyPriority { get; set; } 
} 

// Then in the Linq statement 

(from r in ctx.MyTable where SomeCondition 
    select new CompanyModel() 
    { 
     CompanyId = r.CompanyId, 
     CompanyName = r.CompanyName, 
     CompanyPriority = r.CompanyPriority 
    } 
).Distinct(); 
0

Essayez:

var results = (from company in context.Companies 
    select new { 
     CompanyId = company.CompanyId, 
     CompanyName = company.CompanyName, 
     CompanyPriority = company.CompanyPriority 
    }).Distinct(); 

La clé est d'obtenir les pièces de la requête qui peut être unique ensemble, puis appelez l'extension .Distinct(). Si vous laissez la propriété configID là-dedans, ils seront tous uniques.

0
var query = from c in context.vwCompany 
      group c by new { 
       c.CompanyId, 
       c.CompanyName, 
       c.CompanyPriority } into g 
      select g.Key; 

requête générée (à partir de profils SQL Server) ressemblera:

SELECT 
1 AS [C1], 
[Distinct1].[CompanyId] AS [CompanyId], 
[Distinct1].[CompanyName] AS [CompanyName] 
[Distinct1].[CompanyPriority] AS [CompanyPriority] 
FROM (SELECT DISTINCT 
    [Extent1].[CompanyId] AS [CompanyId], 
    [Extent1].[CompanyName] AS [CompanyName] 
    [Extent1].[CompanyPriority] AS [CompanyPriority] 
    FROM [dbo].[vwCompany] AS [Extent1] 
) AS [Distinct1] 
1

-EDITED: -

Ignorer tout mon code que je l'ai mentionné plus tôt (tout après la fin modifier la section). J'ai essayé plus loin le test. Branchez le code VB suivant et me dire les résultats que vous avez:

(From c In ctx.Companies Select New With { _ 
    Key .companyId = c.CompanyId, _ 
    Key .companyName = c.CompanyName, _ 
    Key .companyPriority = c.CompanyPriority _ 
}).Distinct() 

Je les ai testés à l'aide LINQPad et je me suis l'instruction SQL suivante:

SELECT DISTINCT [t0].[CompanyId] AS [companyId], 
       [t0].[CompanyName] AS [companyName], 
       [t0].[CompanyPriority] AS [companyPriority] 
FROM [Companies] AS [t0] 

-END EDIT-

J'ai eu ce problème il y a quelques jours. C'est ce que j'ai fini par faire.

Ce que vous cherchez nécessiterait la clause GroupBy comme vous l'avez mentionné dans votre message. Juste en utilisant Distinct ne fonctionnera pas comme vous attendriez (autant que je sache). L'expression lambda suivante est ce que j'ai fait et juste après est l'instruction SQL qui est générée par le biais du code lambda.

Lambda code:

Companies.GroupBy(c => new { 
          c.CompanyId, 
          c.CompanyName, 
          c.CompanyPriority 
         }) 
     .Select(p => new { 
          CompanyId = p.Key.CompanyId, 
          CompanyName = p.Key.CompanyName, 
          CompanyPriority = p.Key.CompanyPriority 
         }) 

Code SQL:

SELECT [t0].[CompanyId] AS [companyId], 
     [t0].[CompanyName] AS [companyName], 
     [t0].[CompanyPriority] AS [companyPriority] 
FROM [Companies] AS [t0] 
GROUP BY [t0].[CompanyId], 
     [t0].[CompanyName], 
     [t0].[CompanyPriority] 
+0

Curieusement, cela fonctionne dans LinqPad mais pas dans mon application. Je me demande si c'est parce que c'est contre un IQuerable sur un ObjectSet ou si c'est juste la version de EF sur laquelle le projet a été mis en place. Malheureusement, j'ai été rédigé à mi-chemin pour couvrir le dev original en congé. Quand j'ai un peu de répit, je vais revenir à ça (j'ai 2h jusqu'à la révision de sprint et j'ai besoin de quelque chose qui marche en ce moment: \). – Nick

0

Si pas deux tableaux? Un avec

00001 | Company One | 99 
00002 | Company Two | 99 

Et l'autre avec

00001 | 123 
00001 | 456 
00001 | 789 
00002 | 123 
00002 | 456 

qui est plus normalisée et rendrait votre requête vraiment facile?

+0

Oui, il devrait, malheureusement, cette décision est hors de mes mains :( – Nick