2010-03-15 5 views
1

Selon la façon dont je la carte mes requêtes LINQ à mes objets de domaine, je reçois l'erreur suivanteLINQ to SQL Traduction

Le membre « membre » a pas de traduction pris en charge à SQL.

Ce code provoque l'erreur:

public IQueryable<ShippingMethod> ShippingMethods { 
    get { 
     return from sm in _db.ShippingMethods 
       select new ShippingMethod(
        sm.ShippingMethodID, 
        sm.Carrier, 
        sm.ServiceName, 
        sm.RatePerUnit, 
        sm.EstimatedDelivery, 
        sm.DaysToDeliver, 
        sm.BaseRate, 
        sm.Enabled 
       ); 
    } 
} 

Ce code fonctionne très bien:

public IQueryable<ShippingMethod> ShippingMethods 
{ 
    get 
    { 
     return from sm in _db.ShippingMethods 
       select new ShippingMethod 
       { 
        Id = sm.ShippingMethodID, 
        Carrier = sm.Carrier, 
        ServiceName = sm.ServiceName, 
        EstimatedDelivery = sm.EstimatedDelivery, 
        DaysToDeliver = sm.DaysToDeliver, 
        RatePerUnit = sm.RatePerUnit, 
        IsEnabled = sm.Enabled, 
        BaseRate = sm.BaseRate 
       }; 
    } 
} 

Ceci est mon TestMethod je teste avec:

[TestMethod] 
public void Test_Shipping_Methods() { 
    IOrderRepository orderRepo = new SqlOrderRepository(); 
    var items = orderRepo.ShippingMethods.Where(x => x.IsEnabled); 
    Assert.IsTrue(items.Count() > 0); 
} 

Comment fonctionne la manière que j'instancie mon objet affecte la traduction de linq en sql?

Merci Ben

Répondre

3

Il essaie de retrouver toute requête LINQ to SQL, y compris tous les appels de méthode et de propriété. Les seules exceptions sont la syntaxe de l'initialiseur d'objet (à la fois pour les types anonymes tels que nommés) et les méthodes d'extension qui sont elles-mêmes mappées à SQL (.Count() par exemple).

Petite histoire: vous ne pouvez pas utiliser de constructeurs non-par défaut avec Linq to SQL ou Entity Framework.

+0

Que ferais-je dans le cas où j'ai besoin d'utiliser un constructeur? Par exemple, j'ai besoin d'initialiser l'état de l'objet et ceci est fait en utilisant une énumération qui est conservée dans la base de données. Par conséquent, j'ai besoin de transmettre cette valeur dans le constructeur. Merci –

+0

Vous pouvez avoir un constructeur, mais pas un constructeur avec des paramètres. L'initialisation devrait aller dans le constructeur sans paramètre (= default). –

+0

Ok, mais je crois que l'initialisation en utilisant la syntaxe d'initialisation d'objet ci-dessus frappe le constructeur par défaut avant que les valeurs de propriété ne soient assignées. Donc, il semble que si j'ai besoin d'initialiser une propriété d'état basée sur celle que je suis en train de mapper ci-dessus, je vais devoir ajouter une sorte de méthode initialize et l'appeler après que le mapping soit terminé. –

1

Le problème le plus important ici est que vous mélangez des sémantiques de prédicat et de projection.

Une fois votre projet (par exemple avec select), il n'est plus sûr d'utiliser l'extension Where jusqu'à ce que vous les résultats se matérialisent avec ToList(), ToArray() ou similaire. Le deuxième cas se produit parce que la projection est complètement transparente - tout ce que vous faites est des affectations de propriété, et à la même classe. Les constructeurs ne tombent pas dans cette catégorie; Comme le dit le message d'erreur, il n'y a pas de représentation équivalente d'un appel de constructeur dans SQL Server.

Pourquoi avez-vous besoin de faire cette projection quand même? La propriété entière pourrait être remplacée par juste:

return _db.ShippingMethods.AsQueryable(); 
+0

Ce code n'est probablement pas clair, mais je n'utilise pas les objets Linq. Donc, _db.ShippingMethods renvoie Linq.ShippingMethod mais je suis mappé à MyModel.ShippingMethod. Merci pour votre explication de toute façon. –