2010-02-23 3 views
2

J'ai un problème dans l'architecture de mon application.Comment concevoir mon code de service/référentiel avec Linq2Sql!

J'ai la structure suivante avec seulement les aspects importants montrés.

namespace Domain 
{ 
    public class Invoice 
    { 
    //properties 
    } 

public class InvoiceRepository 
{ 
    public Linq2SqlContext context = new Linq2SqlContext(); 

    public IQueryable<Invoice> GetInvoices() 
    { 
       var query = from inv in _dbctx.Invoices orderby inv.invInvoiceDate descending select GetInvoice(inv) ; 

      return query; 

    } 
} 
public class InvoiceService() 
{ 
    public InvoiceRepository _repository = new InvoiceRepositroy(); 
    public IQueryable<Invoice> GetInvoices() 
    { 
     return _repository.GetInvoices(); 
    } 

} 
} 

namespace MyApp 
{ 
    public class UI 
    { 
     public InvoiceService _service = new InvoiceService(); 
     public void FilterInvoices() 
     { 
      var query = 
        (
        from i in _service.GetInvoices() 
        from s in _service.GetStatuses() 
        where i.ProjectID == _projectid && 
          s.ID == i.Status 
        select new 
        { 
         InvoiceID = i.ID, 
         DocumentTotal = i.TotalDue.ToString(), 
         Created = i.Created, 
         WeekEnding = i.WeekEnding, 
         Status = s.staStatus 
        } 
        ).Skip(_pageIndex * _pageSize).Take(_pageSize); 

     } 

    } 
{ 

Je veux retourner IQueryable de mon service que je puisse filtre à partir du code client. Mais le problème que je rencontre est est les erreurs de la méthode FilterInvoices avec "Non supporté traduction en sql" à cause de la méthode GetInvoice qui est utilisée pour renvoyer une entité Facture (c'est une couche sur le dessus du LInq2 sql layer) et non une entité Linq2sql Invoice.

Alors, comment puis-je retourner un IQueryable de mon service avec cette structure? Aussi comment trier et retourner un IQureyable dans le référentiel GetInvoices.

Espérons que cela a du sens.

Malcolm

Répondre

1

linq2sql pense GetInvoice (au sein GetInvoices) est une procédure stockée. Un moyen de contourner cela

var query = from inv in _dbctx.Invoices orderby inv.invInvoiceDate descending select inv ; 

mais cela repasserait les objets générés par votre datacontext. Si vous souhaitez peupler des objets personnalisés, vous pouvez parcourir la collection en créant vos objets Invoice personnalisés et en les remplissant.

foreach(var inv in query) { somelist.Add(new MyCustomInvoince() { id = inv.id ... } 

EDIT: Ce qui précède va retourner une liste. Utilisez ce qui suit pour retourner IQueryable

return from item in query 
    select GetInvoice(item); 

La différence est à ce stade que vous utilisez Linq2Objects, et ce fournisseur saura comment appeler GetInvoice

-1

Ceci est juste à côté du haut de ma tête, mais vous pouvez essayer:

from i in _service.GetInvoices().AsEnumerable() 
+0

Pourquoi la conversion vers IEnumarable supporterait-elle mieux la traduction vers SQL que IQueryable? – Manu

+0

non, le problème est dans GetInvoices. linq tente de traduire GetINvoice (inv) dans un appel de procédure stockée –

1

Vous ne peut pas interroger avec LTS (LINQ to SQL) quelque chose construit "sur le dessus" de la couche LTS. La raison est que la couche d'entités LTS est un mappage du contenu de votre base de données, et que la requête que vous effectuez est "juste" traduite en SQL.

J'utilise une autre approche pour personnellement garder un independance entre mes couches ...

Je crée interfaces qui correspondent à mes ENTITES LTS, et j'utiliser le Cast <>() Méthode d'avoir mon dépôt retourner l'interface au lieu de l'implémentation concrète.

Cela fonctionne parfaitement.

Vous devez étendre l'entité de base (pas de pb car il est une classe partielle):

partial class Employee : IEmployee 

Et vous avez besoin de cette propriété dans votre dépôt:

public IQueryable<IEmployee> Query 
{ 
    get 
    { 
     return this._context.Employees.Cast<IEmployee>(); 

    } 
} 

Sur cette base, vous pourrait coder un référentiel générique, mais c'est une autre histoire (plus compliqué)

Questions connexes