2010-06-22 4 views
2

J'ai une extension de chaîne C# qui rend vraiment la vie facile, mais je reçois l'exception:Comment adapter une simple extension de chaîne pour soutenir SQL

Method 'System.String ToUrlString(System.String)' has no supported translation to SQL. 

Je l'ai vu cela comme un problème commun et certaines personnes ont trouvé des façons de régler cela pour leur méthode, mais je ne suis pas sûr que ce soit possible pour moi. C'est juste un raccourci simple et j'ai essayé de l'utiliser avec une expression régulière ainsi, et la même exception se présente.

public static string ToUrlString(this String val) 
{ 
    return val.Trim().ToLower().Replace(" ", "-").Replace(":", string.Empty); 
} 

Y a-t-il d'autres décorateurs ou façons dont je peux adapter ce code pour qu'il puisse supporter SQL? J'appelle cela sur la clause where dans mes expressions LINQ. .ToTagString() n'est pas exactement la même méthode que .ToUrlString() mais c'est très similaire.

EDIT: Par une suggestion ci-dessous, voici quelque chose d'autre que j'ai essayé, mais je reçois toujours la même erreur.

public IEnumerable<Post> GetPostsByTag(string tagName) 
{ 
    var query = from p in db.Posts 
      join pt in db.PostTags on p.PostID equals pt.PostID 
      where pt.Tag.TagName.ToTagString().Equals(tagName.ToTagString()) 
      orderby p.PostDate descending 
      select p; 

    var result = query.AsEnumerable(); 

    return from r in result 
      select r; 
} 

Répondre

1

Non, vous ne pouvez pas traduire cela en SQL, au moins sans implémenter votre propre fournisseur LINQ TO SQL. Le problème est que vous l'utilisez dans une requête Linq, donc il essaie de traduire votre méthode en langage SQL.

LINQ utilise IQueryable pour effectuer le travail de traduction de votre expression vers le langage SQL. Lorsque vous utilisez IQueryable (toutes les entités renvoyées à partir du datacontext implémentent IQueryable), toutes les méthodes qui lui sont appliquées seront traduites en SQL.

Pour éviter que votre méthode personnalisée en cours de traduction à SQL, vous devez d'abord convertir votre expression LINQ à IEnumerable, donc pas plus tranlation se produira:

public IEnumerable<String> Example() 
{ 
    var query = from f in foos 
      where f.Id == 'myId' 
      select f; 

    var result = query.AsEnumerable(); 

    return from r in result 
      select r.Url.ToUrlString(); 
} 

Hope it helps!

+0

Je ne suis pas d'accord. Il doit y avoir un moyen, car si vous utilisiez la même condition (.Trim(). ToLower() ....) dans la requête LINQ, cela aurait fonctionné. Dans ce cas, le problème n'est pas que l'une de ces méthodes n'a pas de traduction. En fait, ils ont tous. Le problème est que vous faites un appel de fonction où vous devriez avoir une expression. –

+0

Bien sûr, je devrais également mentionner que, bien que la solution ci-dessus fonctionne, elle a évidemment un inconvénient de performance car vous tirez toutes les lignes de la table et ne filtrez que du côté client. –

+0

Merci pour cette suggestion, j'ai essayé cela, mais la différence est que je ne veux pas appeler cette extension de chaîne sur l'instruction select, mais plutôt je veux l'utiliser dans la clause where sur une colonne db et une chaîne d'entrée à faciliter les comparaisons. – MaseBase

1

Je pense que vous pouvez créer une fonction UDF pour effectuer la manipulation de chaînes requise au niveau de la base de données. http://msdn.microsoft.com/en-us/library/bb386973.aspx http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx

  1. Créer UDF. Utilisez les fonctions LTRIM, RTRIM, LOWER, REPLACE. Quelque chose comme ça.

    CREATE FONCTION dbo.ToUrlString (@string VARCHAR (MAX)) RETURNS VARCHAR (MAX) BEGIN RETOUR REPLACE (REMPLACER (BAS (LTRIM (RTRIM (@string))), '', '-') , ':', '') END

  2. Ajoutez-le comme méthode à votre DataContext. Il suffit de glisser-déposer de Server Explorer sur le concepteur L2S.

J'espère que cela aide.

Questions connexes