0

Inspiré par le battage publicitaire DDD, j'ai conçu mes classes en prétendant qu'il n'y avait aucune base de données. Et puis utilisé NHibernate pour mapper les classes aux tables de base de données. Une partie de mon graphe de classe ressemble à ceci: Ordre (hasmany) -> Produit (belongssto) -> Vendeur. Pour récupérer toutes les commandes passées pour un certain vendeur. J'ai le code:Performances de la base de données avec Nhibernate et Activerecord

public class Order:ActiveRecordBase<Order> 
{ 
    [HasMany] 
    public ICollection<Product> Items{get;set;} 
    ... 
} 

public class Product: Order:ActiveRecordBase<Product> 
{ 
    [BelongsTo] 
    public Seller Seller{get; set;} 
    ... 
} 

public class OrderRepository:IOrderRepository 
{ 
    public IQuerable<Order> GetOrdersBySellerId(int sellerId) 
    { 
     return Order.FindAll().AsQuerable.Where(x=>x.Items.Count > 0 && 
                x.Items.First().Seller.SellerID == sellerId).AsQuerable(); 

    } 
} 

Pas joli, mais cela a fonctionné avec mes tests unitaires. J'étais content jusqu'à ce que nous commencions à injecter de vraies données dans la base de données. La performance est si mauvaise que je veux vomir. J'ai donc fait une petite enquête pour mon code de dépôt. Pas étonnamment, afin de trouver les commandes que je veux, j'ai dû obtenir toutes les données de la table de commande, et toutes les données de la table de produit et quelques données de la table de vendeur.

Alors, voici mon problème. Comme un total de mannequin dans la base de données, je ne sais pas comment améliorer mon code de dépôt même si je sais que ça pue mal. Donc, je suis tenté de modifier ma classe Order pour avoir une référence à la classe Seller, afin que je puisse utiliser hql pour ajouter une clause Where pour améliorer les performances. Mais modifier la structure des classes en raison d'un problème de base de données semble enfreindre les principes DDD.

Quelle est votre suggestion, en particulier pour améliorer mon code de dépôt? J'ai essayé Linq pour ActiveRecord et hql. Mais ne pouvait pas les faire travailler.

Répondre

0

Après beaucoup de recherches, je suis arrivé cette déclaration HQL

public IQuerable<Order> GetOrdersBySellerId(int sellerId) 
{ 
    string hql = @"select o 
        from  Order o, Product p 
        where p.Seller.SellerID=:sellerID 
        and  p in elements(o.Items)"; 

    SimpleQuery<Order> q = new SimpleQuery<Order>(hql); 
    q.SetParameter("sellerID", sellerID); 
      return q.Execute().AsQueryable(); 
} 

Merci pour this poste. J'ai eu l'idée de la réponse d'Ayende. S'il vous plaît laissez-moi savoir si cela va démarrer la performance.

0

Bien que AFAIK ActiveRecord ne dispose pas de la prise en charge directe de LINQ, vous pouvez utiliser le fournisseur LINQ to NHibernate. Here est un exemple. A sa fin il y a un exemple d'utilisation de critères API plus traditionnels et matures.

MISE À JOUR: Désolé, j'avais tort. Il semble que vous ayez besoin d'hériter vos entités de ActiveRecordLinqBase<T> et de générer des requêtes en utilisant sa propriété Queryable.

Il devrait ressembler à

public IQuerable<Order> GetOrdersBySellerId(int sellerId) 
{ 
    return Order.Queryable 
       .Where(x=>x.Items.Count > 0 && x.Items.First().Seller.SellerID == sellerId)(); 
} 

Si vous souhaitez coller avec ActiveRecordBase<T> ordinaire, vous pouvez utiliser la méthode statique ActiveRecordLinq.AsQueryable<T>().

public IQuerable<Order> GetOrdersBySellerId(int sellerId) 
{ 
    return ActiveRecordLinq.AsQueryable<Order>() 
       .Where(x=>x.Items.Count > 0 && x.Items.First().Seller.SellerID == sellerId)(); 
} 

Avez-vous essayé avec vos critères de recherche? (Je demande, parce que vous ne AFAIK toutes les constructions LINQ travaux sur NHibernate)

+0

ActiveRecord prend en charge Linq. Je l'ai découvert à partir de son code source :). Mais je n'ai pas été capable de trouver un code aussi complexe que le mien dans le test d'ActiveRecord :( –

+0

En effet, j'ai corrigé mon message Désolé pour désinformation –

+0

Merci J'ai fait exactement la même chose que votre premier extrait de code (hérité de ActiveRecordLinqBase) Mais j'ai une exception que je suspecte à Items.First(), car First est une méthode d'extension et ActiveRecord Linq n'a pas la bibliothèque pour le comprendre. –

Questions connexes