Linq Query continue de lancer «Impossible de créer une valeur constante de type System.Object…», pourquoi?

94

Voici l'exemple de code:

private void loadCustomer(int custIdToQuery) 
    {
        var dbContext = new SampleDB();
        try
        {
            var customerContext = from t in dbContext.tblCustomers      // keeps throwing:
                                   where t.CustID.Equals(custIdToQuery) // Unable to create a constant value of type 'System.Object'. 
                                   select new                           // Only primitive types ('such as Int32, String, and Guid') 
                                   {                                    // are supported in this context.
                                       branchId = t.CustomerBranchID,   //
                                       branchName = t.BranchName        //
                                   };                                   //

            if (customerContext.ToList().Count() < 1) //Already Tried customerContext.Any()
            {
                lstbCustomers.DataSource = customerContext;
                lstbCustomers.DisplayMember = "branchName";
                lstbCustomers.ValueMember = "branchId";
            }
            else
            {
                lstbCustomers.Items.Add("There are no branches defined for the selected customer.");
                lstbCustomers.Refresh();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {
            dbContext.Dispose();
        }
    }

je suis incapable de comprendre ce que je fais de mal. Je continue à recevoir "Impossible de créer une valeur constante de type" System.Object ". Seuls les types primitifs (" tels que Int32, String et Guid ") sont pris en charge dans ce contexte."

Neel
la source

Réponses:

232

Utilisez == au lieu de Equals:

where t.CustID == custIdToQuery

Si les types sont incorrects, vous pouvez constater que cela ne compile pas.

Mark Byers
la source
10
Pouvez-vous expliquer la différence entre "t.CustID == custIdToQuery" et "t.CustID.Equals (custIdToQuery)". merci d'avance
Neel
2
@Neel Jetez un œil à cette question pour obtenir des explications sur la différence entre ==et .Equals(): stackoverflow.com/questions/814878/…
Alex
La logique de solution 2011 a fonctionné en 2018! Génial digne!
Yeshwant Mudholkar
29

J'ai eu le même problème avec un int nullable. Utiliser == à la place fonctionne bien, mais si vous souhaitez utiliser .Equals, vous pouvez le comparer à la valeur de la variable Nullable, donc

where t.CustID.Value.Equals(custIdToQuery)
kloarubeek
la source
9

J'ai eu le même problème lorsque j'essayais de faire .Equals avec une décimale nullable. L'utilisation de == fonctionne plutôt bien. Je suppose que c'est parce qu'il n'essaie pas de faire correspondre le "type" exact de décimal? en décimal.

Dave Stuart
la source
4
Gardez à l'esprit que cela se situe dans le contexte d'un IQueryable, donc il n'est pas compilé dans du code C # normal. Il devient une expression qui est transmise à un fournisseur de requêtes. Ce fournisseur de requête peut faire tout ce que veut avec la requête, et il peut gérer Equalset ==même ou non.
Servy
J'avais l'habitude .Equal()de comparer Int32?avec Int32. Depuis Int32?est censé contenir Int32et null, j'ai pensé que cela fonctionnerait. Mais ça n'a pas été le cas. ==travaillé.
matrice du
1

J'ai été confronté au même problème et je comparais l'objet de collection "User"avec le type de données entier "userid"( x.User.Equals(userid))

from user in myshop.UserPermissions.Where(x => x.IsDeleted == false && x.User.Equals(userid))

et la requête correcte est x.UserId.Equals(userid)

from user in myshop.UserPermissions.Where(x => x.IsDeleted == false && x.UserId.Equals(userid))
Sonker Satish Kumar
la source
C'est un problème différent, vous comparez des pommes et des oranges.
Lasse V. Karlsen
comment c'est différent. alors que j'ai fait face au même problème. Je viens de poster cette réponse pour référence uniquement pour les autres.
Satish Kumar sonker
0

Dans mon cas, j'ai changé l'appel direct de (sender as Button).Texten appel indirect en utilisant une variable temporaire, cela a fonctionné. code de travail:

private void onTopAccBtnClick(object sender, EventArgs e)
    {
        var name = (sender as Button).Text;
        accountBindingSource.Position =
                    accountBindingSource.IndexOf(_dataService.Db.Accounts.First(ac => ac.AccountName == name));
        accountBindingSource_CurrentChanged(sender, e);
    }

code buggy:

private void onTopAccBtnClick(object sender, EventArgs e)
    {
        accountBindingSource.Position =
                    accountBindingSource.IndexOf(_dataService.Db.Accounts.First(ac => ac.AccountName == (sender as Button).Text));
        accountBindingSource_CurrentChanged(sender, e);
    }
vaheeds
la source