2010-06-05 25 views
2

Son probarbly un problème simple à 3 niveaux. Je veux juste m'assurer que nous utilisons la meilleure pratique pour cela et je ne suis pas encore familier avec les structures.Où les objets fusionnent/joignent-ils des données dans un modèle à trois niveaux?

Nous avons les 3 niveaux:

  • GUI: ASP.NET pour la présentation-couche (première plate-forme)
  • BAL: couche d'affaires sera en charge la logique sur un serveur web en C#, DAL: LINQ to SQL dans la couche de données, renvoyant BusinessObjects non LINQ. LINK à SQL dans la couche de données. DB: Le SQL sera Microsoft SQL Server/Express (encore décidé).

Pensez à la configuration où nous avons une base de données de [Personnes]. Ils peuvent tous avoir plusieurs [Adresse] es et nous avons une liste complète de tous [PostalCode] et des noms de villes correspondants, etc.

L'affaire est que nous avons joint beaucoup de détails d'autres tables.

{Relations}/[tables]

  • [Personne]: 1 --- N: {} PersonAddress: M --- 1: [Adresse]
  • [Adresse]: N --- 1: [Code Postal]

Maintenant, nous voulons construire le DAL pour la personne. Comment devrait ressembler PersonBO et quand les jointures se produisent-elles? Est-ce un problème de couche de gestion pour récupérer tous les noms de villes et adresses possibles pr. La personne? ou le DAL devrait-il terminer tout ceci avant de retourner le PersonBO au BAL?

Class PersonBO 
{ 
    public int ID {get;set;} 
    public string Name {get;set;} 
    public List<AddressBO> {get;set;} // Question #1 
} 

// Q1: récupérons-nous les objets avant de retourner le PersonBO et devrait-il être un tableau à la place? ou est-ce totalement faux pour n-tier/3-tier ??

Class AddressBO 
{ 
    public int ID {get;set;} 
    public string StreetName {get;set;} 
    public int PostalCode {get;set;} // Question #2 
} 

// Q2: faisons-nous la recherche ou laissons simplement le code postal pour une consultation ultérieure? Est-ce que quelqu'un peut expliquer dans quel ordre tirer quels objets? La critique constructive est la bienvenue. : 0)

Répondre

1

Vous êtes en quelque sorte de réinventer la roue; ORMs déjà résoudre la plupart de ce problème pour vous et vous allez trouver un peu difficile à faire vous-même. La façon dont les ORM tels que Linq to SQL, Entity Framework et NHibernate font ceci est une technique appelée chargement paresseux des associations (qui peuvent être éventuellement remplacées par une charge ardente).

Lorsque vous déplacez un Person, il ne charge pas le Address jusqu'à ce que vous le demandiez spécifiquement, auquel cas un autre aller-retour à la base de données se produit (chargement paresseux). Vous pouvez également spécifier sur une base par requête que vous voulez que le Address soit chargé pour chaque personne (chargement hâtif).Dans un sens, avec cette question, vous demandez essentiellement si vous devez ou non effectuer des charges paresseuses ou ardentes du AddressBO pour le PersonBO, et la réponse est: ni l'un ni l'autre. Il n'y a pas une seule approche qui fonctionne universellement. Par défaut vous devriez probablement charger paresseux, de sorte que vous ne faites pas beaucoup de jointures inutiles; afin de tirer ceci, vous devrez construire votre PersonBO avec un mécanisme de chargement paresseux qui maintient une référence à la DAL. Mais vous voudrez toujours avoir l'option de chargement rapide, que vous aurez besoin de construire dans votre logique "d'accès aux entreprises". Une autre option, si vous devez renvoyer un ensemble de données hautement personnalisé avec des propriétés spécifiques provenant de nombreuses tables différentes, est de ne pas renvoyer de PersonBO du tout, mais d'utiliser un Data Transfer Object (DTO). Si vous implémentez un mécanisme de chargement paresseux par défaut, vous pouvez parfois le remplacer par la version "chargement rapide".


Pour votre information, les chargeurs paresseux dans les cadres d'accès aux données sont généralement construites avec la logique de chargement dans l'association elle-même:

public class PersonBO 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public IList<AddressBO> Addresses { get; set; } 
} 

Ceci est juste un POCO, la magie se produit dans la mise en œuvre de la liste réelle:

// NOT A PRODUCTION-READY IMPLEMENTATION - DO NOT USE 

internal class LazyLoadList<T> : IList<T> 
{ 
    private IQueryable<T> query; 
    private List<T> items; 

    public LazyLoadList(IQueryable<T> query) 
    { 
     if (query == null) 
      throw new ArgumentNullException("query"); 
     this.query = query; 
    } 

    private void Materialize() 
    { 
     if (items == null) 
      items = query.ToList(); 
    } 

    public void Add(T item) 
    { 
     Materialize(); 
     items.Add(item); 
    } 

    // Etc. 
} 

(Ce n'est évidemment pas de qualité de production, c'est juste pour démontrer la technique, vous commencez par une requête et ne matérialisez pas la liste réelle jusqu'à ce que vous deviez le faire.)

+0

Merci pour votre temps et vos efforts, je connais le principe de la charge paresseuse, je pense que c'est plus une question d'où mettre quel code ou quelle classe devrait effectuer quelle action afin d'être "bon niveau" design. Je voudrais séparer les niveaux "par les meilleures pratiques", mais j'ai du mal à comprendre comment une fonction "PersonBAL.GetAll()" retournera des données et si ce sont vraiment des éléments "unLINQed" comme cela pourrait être un webservice demandant les données + comment le h *** garde-t-on l'objet/ID pour sauvegarder/mettre à jour quand le niveau de l'interface graphique publie? – BerggreenDK

+0

@Berggreen: Je suis assez certain d'avoir répondu à cette question. le code de chargement paresseux va dans la collection elle-même ou dans la propriété getter (si c'est une association 1: 1). Si vous essayez d'exposer ce type d'API sur un service Web, vous vous trompez; les services Web exposent les opérations, pas les données. Cela dit, pour les rares occasions où vous avez besoin de retourner des relations profondément imbriquées à travers un service web, la solution typique est de permettre au consommateur de spécifier, dans la requête, quelles associations charger, et de laisser le reste comme null '/ vide (pas de chargement paresseux). – Aaronaught

+0

okay, je pourrais ne pas avoir compris votre réponse complètement, mais je marquerai comme la réponse alors. : o) merci encore !! – BerggreenDK