web-dev-qa-db-fra.com

Impossible d'utiliser une expression lambda en tant qu'argument dans une opération à distribution dynamique sans l'avoir préalablement convertie en type de délégué ou d'arborescence d'expression.

Je travaille avec .NET4.5 et VS2013, j'ai cette requête qui obtient le résultat de dynamic de db.

dynamic topAgents = this._dataContext.Sql(
    "select t.create_user_id as \"User\", sum(t.netamount) as \"Amount\" from transactiondetail t where t.update_date > sysdate -7 group by t.create_user_id")
    .QueryMany<dynamic>();

L'instruction suivante échoue avec l'erreur de compilation Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type Sans même m'autoriser à l'exécuter

topAgents.ToList().Select(agent => new
{
    User = agent.User != null ? string.Format("{0}", agent.User).Replace("CORPNTGB\\", "") : null,
    Amount = agent.Amount
});

tandis que celui avec foreach fonctionne très bien.

var data = new List<List<object>>();
foreach (dynamic agent in topAgents)
{
    data.Add(new List<object>
    {
        agent.User != null ? string.Format("{0}", agent.User).Replace("CORPNTGB\\", "") : null,
        agent.Amount
    });
}

À mes yeux, après je topAgents.ToList(), ils pourraient être interprétés comme équivalents. Est-ce parce que je déclare explicitement que var data = new List<List<object>>(); cette deuxième instruction est autorisée par le compilateur?

Pourquoi le compilateur n'autorise-t-il pas LINQ à sélectionner, mais autorise-t-il chaque option?

58
Matas Vaitkevicius

Le problème est que topAgents est dynamic - votre appel ToList() est donc dynamique, et donc Select. Cela a des problèmes qui:

  1. vous ne pouvez pas utiliser d'expressions lambda pour des appels dynamiques comme celui-ci;
  2. les appels dynamiques ne trouvent pas les méthodes d'extension de toute façon.

Heureusement, les opérations n'ont pas besoin d'être dynamiques simplement parce que le type element est dynamique. Vous pouvez utiliser:

IEnumerable<dynamic> topAgents = ...;

... ou utilisez simplement var. Les deux devraient aller bien.

82
Jon Skeet