-1
votes

L'expression LINQ ne peut pas être traduite - c #

J'ai écrit une requête simple (problèmes est quand j'essaie de définir une adresse code> ci-dessous CodeCode code>):

//Address = new AddressDTO 
//{
//    Address = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Address,
//    Country = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Country,
//    Zip = x.Product.Addresses.OrderBy(x => x.CreatedDate).FirstOrDefault().Zip,
//},


2 commentaires

Vous ne pouvez pas appeler mapper de votre requête car ef ne sait pas comment traduire cela en SQL. Peut-être la restructurer pour renvoyer vos données en premier (utilisez peut-être un objet anonyme pour la propriété d'adresse), puis appelez mapper une fois que vous avez vos données de la base de données.


@Matthewlayton merci pour une réponse rapide Matthew! Puissiez-vous fournir une sorte d'exemple pour que je puisse essayer de le faire maintenant? Comment pourrais-je le résoudre avec un objet anonyme pour la propriété d'adresse?


3 Réponses :


5
votes

Problément d'entité framework traduit ce code en SQL et votre méthode de la carte mappe () code> est inconnue de SQL. Heureusement, cette méthode ne fait pas grand chose, vous devriez donc être capable de déplacer sa fonctionnalité directement sur la requête.

Vous pouvez utiliser .select () code> pour projeter la collection dans un nouveau type (juste Comme vous le faites déjà pour construire votre productDo code>). p>

Par exemple: p>

//...
Address = x.Product.Addresses.OrderBy(x=> x.CreatedDate)
                             .Select(x=> new AddressDTO
                             {
                                 Address = x.Address,
                                 Country = x.Country,
                                 Zip = x.Zip
                             })
                             .FirstOrDefault()
//...


0 commentaires

0
votes

Voir la réponse de David ci-dessus pour expliquer pourquoi il ne fonctionne pas.

Pour une solution de contournement, vous pouvez appeler .tolist () avant la mappage de sorte que la requête soit exécutée sur le serveur: P>

_connectDBContext.Products
  .Join(...)
  .Where(x => x.Id == x.CustomerRelationId)
  .ToList() // !!!
  .Select(x => new ProductDto
     {
        Title = x.Product.Title,
        ProductCode = x.Product.Code,
        Address = Map(x.Product.Addresses.OrderBy(x=> x.CreatedDate).FirstOrDefault()),
...
     });
                        


2 commentaires

Mais cela signifie que tous les produits plus des données jointes seront mis dans votre mémoire. Tolist () est un tueur de performance!


vrai, pas optimal. C'est la raison pour laquelle vous déplacez la clause où la clause de TOLIST pour limiter le nombre de résultats tôt. Vous devez comprendre ce qui se passe et quelles sont les conséquences. Pour que le petit jeu de résultats est correct, pour un plus grand nombre d'éléments - besoin d'optimiser.



0
votes

Vous ne pouvez pas appeler la fonction map tel qu'il est, mais vous pouvez le modifier un peu à fonctionner sur les requêtes sur les requêtes

var query = _connectDBContext.Products
                            .Join(_context.CustomerRelations,
                                Product => Product.ForeignKeyId,
                                CustomerRelation => CustomerRelation.CompanyId,
                                (Product, CustomerRelation) => new { Product, CustomerRelation })
                            .Select(x => new ProductDto
                            {
                                Title = x.Product.Title,
                                ProductCode = x.Product.Code,
                                Address = Map(x.Product.Addresses),
                               
                            })
                            .Where(x => x.Id == x.CustomerRelationId);

           // Rest of the code
        }

private AddressDTO Map(IQueryable<Address> addresses)
{
    return addresses.OrderBy(x => x.CreatedDate).Select(x => new AddressDTO
    {
        Address = address.Address,
        Country = address.Country,
        Zip = address.Zip
    }).FirstOrDefault();
}


0 commentaires