2010-11-29 5 views
8

J'ai une table de base de données qui contient une colonne nvarchar comme ceci:String.Split dans une requête Linq-To-SQL?

1|12.6|18|19 

J'ai un objet d'affaires qui possède une propriété décimale [].

Ma requête LINQ ressemble à ceci:

var temp = from r in db.SomeTable select new BusinessObject { 
    // Other BusinessObject Properties snipped as they are straight 1:1 
    MeterValues = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray() 
}; 
var result = temp.ToArray(); 

Cela jette un NotSupportedException: Method 'System.String[] Split(Char[])' has no supported translation to SQL.

qui suce un peu :) Est-il possible que je peux le faire sans avoir à ajouter une propriété de chaîne à la objet métier ou en sélectionnant un type anonyme, puis itérer à travers elle?

Ma "solution" actuelle est:

var temp = from r in db.SomeTable select new { 
    mv = r.MeterValues, 
    bo = new BusinessObject { // all the other fields } 
}; 
var result = new List<BusinessObject>(); 
foreach(var t in temp) { 
    var bo = t.bo; 
    bo.MeterValues = t.mv.Split('|').Select(Decimal.Parse).ToArray(); 
    result.Add(bo); 
} 
return result.ToArray(); // The Method returns BusinessObject[] 

C'est un peu moche mais, avec cette liste temporaire.

J'ai essayé d'ajouter un let mv = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray() mais cela conduit essentiellement à la même NotSupportedException.

Ceci est .net 3.5SP1 si cela est important.

Répondre

6

Vous devez forcer la clause select à exécuter sur le client en appelant .AsEnumerable() premier:

var result = db.SomeTable.AsEnumerable().Select(r => new BusinessObject { 
    ... 
    MeterValues = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray() 
}).ToList(); 
+1

Est-ce que cela sélectionne la totalité de la table SomeTable? –

+0

@Michael: Oui. Vous devez sélectionner la table entière de toute façon. Si vous avez seulement besoin d'un sous-ensemble des champs, vous pouvez mettre un 'Select' initial avant le' .AsEnumerable'. – SLaks

+2

Oui, ce n'est pas l'idéal - il va essentiellement exécuter un "SELECT * FROM SomeTable". Est-ce que L2SQL supporte les UDF? EF le fait (je pense). Si oui, vous pourriez faire ce split côté serveur (par exemple UDF) – RPM1984

1

Malheureusement son du IQueryable que vous utilisez (LINQ to SQL) qui ne supporte pas la fonction Split.

Vous n'êtes vraiment parti qu'avec le support IEnumerable (Linq to Objects) dans ce cas. Vous deuxième extrait de code est ce que vous devez faire, ou quelque chose comme ...

var temp = (from r in db.SomeTable select new { 
    mv = r.MeterValues, 
    bo = new BusinessObject { // all the other fields } 
}).AsEnumerable().Select(blah, blah) ; 
2

Vous n'avez pas besoin d'utiliser une liste temporaire:

var query = from r in db.SomeTable 
      select new 
      { 
       r.Id, 
       r.Name, 
       r.MeterValues, 
       ... 
      }; 

var temp = from x in query.AsEnumerable() 
      select new BusinessObject 
      { 
       Id = x.Id, 
       Name = x.Name, 
       MeterValues = x.mv.Split('|').Select(Decimal.Parse).ToArray(), 
       ... 
      }; 

return temp.ToArray(); 
2

Vous ne pouvez pas utiliser Split, mais dans ce scénario, vous pouvez effectuer les opérations suivantes:

// Database value is 1|12.6|18|19 

string valueToFind = "19"; 

var temp = from r in db.SomeTable.Where(r => ("|" + r.MeterValues + "|").Contains("|" + valueToFind + "|")); 

ce code ajoute les tuyaux extérieurs (|) à la valeur de base de données à la volée à l'intérieur de la requête afin que vous puissiez le faire démarrer, au milieu, et la valeur finale correspond à la chaîne. Par exemple, le code ci-dessus recherche "| 19 |" à l'intérieur "| 1 | 12.6 | 18 | 19 |", qui est trouvé et valide. Cela fonctionnera pour tout autre valueToFind.

Questions connexes