44 votes

LINQ to SQL et le modèle de référentiel

J'ai l'impression de courir en cercles. Je n'arrive pas à me décider sur ce que la droite modèle de référentiel est à l'aide de LINQ to SQL. Si vous êtes familier avec Rob Conery du MVC Vitrine , vous verrez que sa mise en œuvre enveloppe le LINQ modèles générés avec une autre classe et traite le LINQ généré simplement comme un objet de transfert de données (DTO). Il ressemble à quelque chose comme ceci:

//Custom wrapper class.
namespace Data
{
    public class Customer
    {
         public int Id {get;set;}
         public string Name {get;set;}
         public IList<Address> Addresses {get;set;}
    }
}

//Linq-Generated Class - severly abbreviated
namespace SqlRepository
{
    public class Customer
    {
         public int Id {get;set;}
         public string Name {get;set;}
         public EntitySet<Address> {get;set;}
    }
}

//Customer Repository
namespace SqlRepository
{
    public class UserRepository : IUserRepository
    {
        private _db = new DB(); //This is the Linq-To-Sql datacontext

        public IQueryable GetCusomters()
        {
            return
                from c in _db.Customers
                select new Customer // This is the wrapper class not the gen'd one
                {
                   Id = c.Id,
                   Name = c.Name,
                   Addresses = new LazyList(c.Addresses)
                };
        }

Quel est l'avantage de cette façon de faire (à l'aide d'une classe wrapper), par opposition à la façon dont Mike Hadlow suggère, à l'Aide de la IRepository modèle avec LINQ to SQL dans sa version de IRepository<T>, où il retourne juste la DTO des objets du référentiel?

Où la logique métier être appliquées et contrôlées? Est-ce dans un autre calque, tous ensemble, appelé par le référentiel sur enregistrer/mettre à jour, ou est-il intégré à la classe wrapper?

49voto

Matt Briggs Points 20291

Le truc, c'est cela, LINQ to SQL n'est pas une véritable Relation d'Objet Mappeur (ORM), c'est une couche d'accès aux données du générateur. Vous pouvez faire un ORM par aller en profondeur par la main de l'édition de fichiers XML et de jouer avec SqlMetal et autres joyeusetés, mais là où elle brille comme un DAL.

L'idée derrière un ORM est-ce. Vous avez votre base de données SQL, et votre domaine d'objets. La conception d'une base de données correctement, vous allez faire des choses (comme la normalisation) qui, logiquement, ne se traduisent pas dans un plan bien conçu modèle objet, et vice-versa. Ceci est appelé "adaptation d'Impédance", le rôle d'un ORM est de faire face à cette situation dans un endroit propre, efficace, et efficace. Le moins douloureux interaction de base de données est presque secondaire chose.

L'idée derrière un référentiel, c'est qu'il est un condensé de tous persistance de la logique et des dépendances sur l'infrastructure du reste de votre application. Lorsque votre application a besoin d'un Client de l'objet, il ne devrait pas avoir pour savoir si elle est à venir à partir de SQL Server, MySQL, un fichier XML, ou ASP.NET l'Adhésion. Une fois que vous avez que de couplage, toutes les modifications que vous apportez à votre persistance de l'histoire n'ont aucun effet sur le reste de votre application.

Avec cela à l'esprit, il devient de plus en plus clair pourquoi il a fait ce qu'il a fait. LINQ to SQL est utilisé pour générer le DAL, mais la seule chose qui doit être connu sur le DAL est le dépôt, donc la traduction est faite à son domaine d'objets. De cette façon, il peut refactoriser son modèle de domaine sans se soucier de sa persistance histoire, et il peut refactoriser sa base de données sans se soucier de l'ondulation des effets par le biais de son application. Il pourrait aussi commencer à coder sur une logique d'entreprise avant de décider sur des questions comme ce ORM à utiliser, ou même de l'endroit où stocker ses données.

S'il devait utiliser un vrai ORM (comme NHibernate), que la cartographie code est traité ailleurs (que ce soit en XML ou d'amorçage classes). Je pense que LINQ to SQL (et Prive open source DAL, Subsonique) sont de grands projets, mais plus conçu pour les petits, deux applications de la couche où quelque chose comme le modèle de référentiel est exagéré. La devanture est également une bonne illustration de pourquoi la complexité supplémentaire de NHibernate peut être important. Il aurait pu lui-même sauvé beaucoup de code en allant avec quelque chose de construit pour traiter ce genre de scénario, plutôt que de le faire manuellement.

13voto

Marc Gravell Points 482669

Cela dépend d'où la Dto sont définis et comment vous voulez le tester. Si vous utilisez des DBML, puis LINQ to SQL veut générer les objets de données dans la couche de données. Alors que LINQ to SQL prend en charge la persistance de l'ignorance, il ne veut pas sortir de sa façon de faire, c'est facile. Entity Framework ne prend pas en charge.

Cela signifie que dans le modèle standard, votre couche de données est la définition de l'ensemble du domaine des entités, ce qui est difficile si vous voulez tester l'interface utilisateur/couches de gestion d'un véritable isolement à partir de la couche de données.

Une approche pragmatique pourrait être d'utiliser les données, les définitions d'objets de la couche de données dans les tests unitaires, mais pas les données de contexte (c'est à dire cacher les données de contexte derrière le référentiel de l'interface, mais d'exposer les types d'entité) - mais c'est pour brouiller les cartes un peu, et signifie que votre INTERFACE, etc. besoin d'fortement de référence de la couche de données. Mais si vous pensez à cela comme un "modèle de domaine de la couche qui se trouve également contenir un référentiel de mise en œuvre que l'on peut ou ne peut pas être à l'aide de" on pourrait la justifier.

En gardant complètement séparée de domaine entités qui rend les tests unitaires et d'inversion de contrôle (IoC) plus "pure", mais augmente la quantité de code (donc à double tranchant).

2voto

Andrei Rînea Points 7554

Sont générés les objets sérialisables? J'ai eu l'impression qu'ils ne l'étaient pas. C'est juste une affaire de l'isolement comme Marc Gravier dit ci-dessus.

Que faire si vous passez le référentiel et d'avoir une base de données MySQL, Oracle, XML, Web service, ou quel que soit le fournisseur de données (Référentiel)? Vous serait liée à l'LINQ to SQL assemblée pour faire référence à des entités, à droite? Ce qui, bien sûr, vous ne voulez pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X