web-dev-qa-db-fra.com

Problème avec la conversion de int en chaîne dans Linq en entités

var items = from c in contacts
            select new ListItem
            {
                Value = c.ContactId, //Cannot implicitly convert type 'int' (ContactId) to 'string' (Value).
                Text = c.Name
            };
var items = from c in contacts
            select new ListItem
            {
                Value = c.ContactId.ToString(), //Throws exception: ToString is not supported in linq to entities.
                Text = c.Name
            };

Y a-t-il un moyen de faire cela? Notez que dans VB.NET il n'y a pas de problème, utilisez le premier extrait qui fonctionne à merveille, VB est flexible, je ne parviens pas à m'habituer à la rigueur de C # !!!

199
Shimmy

Avec EF v4, vous pouvez utiliser SqlFunctions.StringConvert . Il n'y a pas de surcharge pour int, vous devez donc utiliser un double ou un nombre décimal. Votre code finit par ressembler à ceci:

_var items = from c in contacts
            select new ListItem
            {
                Value = SqlFunctions.StringConvert((double)c.ContactId).Trim(),
                Text = c.Name
            };
_
310
Brian Cauthon

J'ai résolu un problème similaire en plaçant la conversion de l'entier en chaîne en dehors de la requête. Ceci peut être réalisé en mettant la requête dans un objet.

var items = from c in contacts
            select new 
            {
                Value = c.ContactId,
                Text = c.Name
            };
var itemList = new SelectList();
foreach (var item in items)
{
    itemList.Add(new SelectListItem{ Value = item.ContactId, Text = item.Name });
}
12
Jente Rosseel

Utilisez LinqToObject: contacts .AsEnumerable ()

var items = from c in contacts.AsEnumerable()
            select new ListItem
            {
                Value = c.ContactId.ToString(),
                Text = c.Name
            };
9
Mohammadreza

SqlFunctions.StringConvert fonctionnera, mais je trouve cela fastidieux et, la plupart du temps, je n'ai pas réellement besoin d'effectuer la conversion de chaîne du côté SQL.

Ce que je fais si je veux faire des manipulations de chaîne, c'est d'abord exécuter la requête dans linq-to-entity, puis manipuler les commandes dans linq-to-objects. Dans cet exemple, je souhaite obtenir un ensemble de données contenant le nom complet d'un contact, ainsi que ContactLocationKey, qui est la concaturation de chaîne de deux colonnes de type Integer (ContactID et LocationID).

// perform the linq-to-entities query, query execution is triggered by ToArray()
var data =
   (from c in Context.Contacts
   select new {
       c.ContactID,
       c.FullName,
       c.LocationID
   }).ToArray();

// at this point, the database has been called and we are working in
// linq-to-objects where ToString() is supported
// Key2 is an extra example that wouldn't work in linq-to-entities
var data2 =
   (from c in data
    select new {
       c.FullName,
       ContactLocationKey = c.ContactID.ToString() + "." + c.LocationID.ToString(),
       Key2 = string.Join(".", c.ContactID.ToString(), c.LocationID.ToString())
    }).ToArray();

Maintenant, je reconnais qu’il est fastidieux d’écrire deux sélections anonymes, mais j’arguerais que c’est plus pratique que de pouvoir utiliser des fonctions de chaîne (et d’autres) non prises en charge dans L2E. N'oubliez pas non plus que cette méthode entraîne probablement une baisse des performances.

5
Walter Stabosz
public static IEnumerable<SelectListItem> GetCustomerList()
        {
            using (SiteDataContext db = new SiteDataContext())
            {
                var list = from l in db.Customers.AsEnumerable()
                           orderby l.CompanyName
                           select new SelectListItem { Value = l.CustomerID.ToString(), Text = l.CompanyName };

                return list.ToList();
            }
        }
4
Nestor
var selectList = db.NewsClasses.ToList<NewsClass>().Select(a => new SelectListItem({
    Text = a.ClassName,
    Value = a.ClassId.ToString()
});

Tout d’abord, convertissez en objet, puis toString () sera correct.

3
phil hong

La réponse de Brian Cauthon est excellente! Juste une petite mise à jour, pour EF 6, la classe a été déplacée vers un autre espace de noms. Donc, avant EF 6, vous devriez inclure:

System.Data.Objects.SqlClient

Si vous mettez à jour vers EF 6, ou utilisez simplement cette version, incluez:

System.Data.Entity.SqlServer

En incluant l'espace de noms incorrect avec EF6, le code se compilera parfaitement mais générera une erreur d'exécution. J'espère que cette note aidera à éviter une certaine confusion.

3
Leo

Si votre "contact" agit comme une liste générique, j'espère que le code suivant fonctionnera bien.

var items = contact.Distinct().OrderBy(c => c.Name)
                              .Select( c => new ListItem
                              {
                                Value = c.ContactId.ToString(),
                                Text = c.Name
                              });

Merci.

2
Nawaz

J'ai rencontré ce même problème lorsque je convertissais mon application MVC 2 en MVC 3 et juste pour donner une autre solution (propre) à ce problème, je souhaite publier ce que j'ai fait ...

IEnumerable<SelectListItem> producers = new SelectList(Services.GetProducers(),
    "ID", "Name", model.ProducerID);

GetProducers () renvoie simplement une collection d'entités de producteurs. P.S. Le SqlFunctions.StringConvert n'a pas fonctionné pour moi.

2
BarryC

Une autre solution:

c.ContactId + ""

Ajoutez simplement une chaîne vide et il sera converti en chaîne.

1
Igor Valikovsky

si vous utilisez un framework d'entité et que vous voulez rendre le seul int acceptable, alors vous pouvez utiliser ceci dans une requête linq, vous pouvez essayer ceci

var items = from c in contacts
        select new ListItem
        {
            Value = (int)ContractId 
            Text = c.Name
        };

cela fonctionnera car using (int) va transtyper votre valeur sur int, vous n'aurez donc besoin d'aucune conversion pour string en int et vous obtiendrez le résultat souhaité.

cela a fonctionné pour moi dans mon projet, je pense que ce serait utile pour vous

1
Saurabh Solanki

En utilisant MySql, le SqlFunctions.StringConvert ne fonctionnait pas pour moi. Dans la mesure où j’utilise SelectListItem dans plus de 20 lieux de mon projet, je souhaitais une solution qui fonctionne sans contourner les 20 instructions LINQ. Ma solution a été de sous-classe SelectedListItem afin de fournir un séparateur d'entiers, qui éloigne LINQ de la conversion de type. Évidemment, cette solution est difficile à généraliser, mais a été très utile pour mon projet spécifique.

Pour l'utiliser, créez le type suivant et utilisez-le dans votre requête LINQ à la place de SelectedListItem et utilisez IntValue à la place de Value.

public class BtoSelectedListItem : SelectListItem
{
    public int IntValue
    {
        get { return string.IsNullOrEmpty(Value) ? 0 : int.Parse(Value); }
        set { Value = value.ToString(); }
    }
}
1
raider33