2009-08-07 6 views
3

SQL C Vu le tableau suivant:LINQ to # COALESCE

Length | Width | Color | ID 
=========================== 
    18 | 18 | blue | 1 
--------------------------- 
    12 | 12 | red | 1 
--------------------------- 

Je veux produire une seule colonne/ligne:

SIZES 
================= 
18 x 18, 12 x 12, 

Je peux le faire dans SQL comme suit:

DECLARE @SIZES VARCHAR(8000) 
SELECT @SIZES = COALESCE(@SIZES, '') + Convert(varchar(80), [Length]) + ' x ' + 
       Convert(varchar(80), [Width]) + ', ' 
FROM table 
where ID = 1 
GROUP BY [Length], [Width] 
ORDER BY [Length], [Width] 
SELECT SIZES = @SIZES 

Mais je ne peux pas comprendre comment faire cela dans LINQ.

Le plus proche je suis arrivé était:

from t in table 
where id == 1 
group t by new { 
       t.Length, 
       t.Width 
       } into g 
orderby g.Key.Length, g.Key.Width 
select new { 
      SIZES = (Convert.ToInt32(g.Key.Length) + " x " + 
         Convert.ToInt32(g.Key.Width) + ", ") 
      } 

qui produit une colonne et deux lignes:

SIZES 
======== 
18 x 18, 
12 X 12, 

Les convertis ne sont pas importants au problème. Les colonnes sont définies comme des flottants bien que tous soient des entiers. La clé est la fonction COALESCE Je ne peux pas comprendre comment faire cela dans LINQ.

+0

Comme les autres l'ont souligné, LINQ et T-SQL ne sont pas identiques en termes de fonctionnalités, mais j'ai une question pour votre SQL: Pourquoi le coalesce? Pourquoi ne pas simplement faire "SET @SIZES = ''" avant l'instruction select, opposée à la coalescence sur chaque ligne – John

Répondre

1

Je ne pense pas que LINQ to SQL prend en charge cette astuce T-SQL. Le COALESCE n'est pas vraiment le problème (comme Mehrdad souligne l'équivalent en C# ??) - c'est le fait que SQL Server agrège chaque résultat via la concaténation de chaînes dans la variable @SIZES. AFAIK LINQ to SQL ne peut pas construire ce type de requête.

Cela donnera le résultat souhaité, mais la concaténation de chaîne est effectuée sur votre côté, pas sur le serveur SQL. Cela n'a probablement pas d'importance.

var query = 
    from t in table 
    where id == 1 
    group t by new { 
       t.Length, 
       t.Width 
       } into g 
    orderby g.Key.Length, g.Key.Width 
    select new { 
      SIZES = (Convert.ToInt32(g.Key.Length) + " x " + 
         Convert.ToInt32(g.Key.Width) + ", ") 
      }; 

var result = string.Join(string.Empty, query.Select(r => r.SIZES).ToArray()); 
7

Essayez ?? (null coalesce operator) comme:

t.Length ?? 0 
+0

En utilisant LINQ to SQL ceci génère COALESCE dans le T-SQL résultant –

+0

Sur EF 6 cela devient un 'CASE' déclaration. –

0

Je voudrais juste revenir les int tailles de SQL et faire le bâtiment de chaîne côté client:

var query = 
    from t in table 
    where id == 1 
    group t by new { 
       t.Length, 
       t.Width 
       } into g 
    orderby g.Key.Length, g.Key.Width 
    select g.Key; 

var sizeStrings = from s in query.AsEnumerable() 
        select string.Format("{0} x {1}", s.Length, s.Width); 

var result = string.Join(", ", sizeStrings.ToArray()); 
0

Vous pouvez utiliser la fonction .Aggregate, comme ceci:

(from t in table 
where id == 1 
group t by new { 
      t.Length, 
      t.Width 
      } into g 
orderby g.Key.Length, g.Key.Width 
select new { 
     SIZES = (Convert.ToInt32(g.Key.Length) + " x " + 
        Convert.ToInt32(g.Key.Width) + ", ") 
     }).Aggregate((x,y) => x + y) 

Cela devrait déclencher une seule chaîne, comme vous le souhaitez. Agréger simplement interne maintient exactement la même variable que vous avez définie dans le SQL, juste implicitement.