2

Его простейшая простая проблема с тремя уровнями. Я просто хочу убедиться, что мы используем для этого наилучшую практику, и я еще не настолько популярен со структурами.Где объекты объединяются/объединяются в трехмерную модель?

У нас есть 3 уровня:

  • GUI: ASP.NET для презентационного слоя (первая платформа)
  • BAL: Бизнес-слой будет обработка логики на веб-сервере в C#, поэтому мы оба можем использовать его для webforms/MVC + webservices
  • DAL: LINQ to SQL на уровне данных, возвращая BusinessObjects не LINQ.
  • DB: SQL будет Microsoft SQL-server/Express (еще не принят).

Давайте подумаем о настройке, где у нас есть база данных [Персон]. Они могут иметь несколько [Адрес], и у нас есть полный список всех [PostalCode] и соответствующих имен городов и т. Д.

Сделка заключается в том, что мы объединили множество подробностей из других таблиц.

{отношения}/[Таблица]

  • [Человек]: 1 --- Н: {PersonAddress}: М --- 1: [адрес]
  • [адрес]: N --- 1: [PostalCode]

Теперь мы хотим построить DAL для Person. Как должен выглядеть PersonBO и когда происходит объединение? Проблема бизнес-уровня для получения всех имен города и возможных адресов. Человек? или должен ли DAL завершить все это до возвращения PersonBO в BAL?

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

// Q1: восстанавливаем ли мы объекты перед возвратом PersonBO и, если это будет массив? или это совершенно неправильно для n-level/3-level?

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

// Q2: мы делаем поиск или просто оставляем PostalCode для последующего поиска?

Может ли кто-нибудь объяснить, в каком порядке тянуть какие предметы? Конструктивная критика очень приветствуется. : o)

ответ

1

Вы как бы изобретаете колесо; ORM уже решают большую часть этой проблемы для вас, и вы обнаружите, что это немного сложно сделать самому.

Способ, которым ORM, такие как Linq to SQL, Entity Framework и NHibernate, - это метод, называемый ленивой загрузкой ассоциаций (которые могут быть переопределены с высокой нагрузкой).

Когда вы подтягиваете Person, он не загружает Address, пока вы не спросите его об этом, и в этот момент наступает другая обратная связь с базой данных (ленивая загрузка). Вы также можете указать для каждого запроса, что вы хотите загрузить Address за каждый человек (с нетерпением).

В некотором смысле, с этим вопросом вы в основном спрашиваете, следует ли вам выполнять ленивые или нетерпеливые грузы AddressBO для PersonBO, и ответ: нет. Нет универсального подхода. По умолчанию вам, вероятно, должна быть ленивая нагрузка, чтобы вы не делали много ненужных объединений; чтобы вытащить это, вам нужно будет построить свой PersonBO с помощью механизма ленивой загрузки, который поддерживает некоторую ссылку на DAL. Но вы по-прежнему хотите иметь возможность загружать электронную загрузку, которую вам нужно будет встроить в логику «бизнес-доступ».

Другой вариант, если вам нужно вернуть высоко настраиваемый набор данных со специфическими свойствами, заполненными из разных таблиц, - это не возвращать PersonBO, а вместо этого использовать Data Transfer Object (DTO). Если вы реализуете механизм lazy-load по умолчанию, вы можете иногда заменить его как версию с нетерпением загрузки.


FYI, ленивые грузчики в рамках доступа к данным, как правило, построены с погрузочной логикой в ​​самой ассоциации:

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

Это просто ПОКО, волшебство происходит в фактической реализации списка:

// 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. 
} 

(Это явно не производственный класс, это просто демонстрация техники, вы начинаете с запроса и не выполняете фактический список до тех пор, пока вам не понадобится.)

+0

Спасибо за ваше время и усилия, я знаю о принципе ленивой нагрузки, я думаю, что это больше вопрос о том, где поставить какой код или какой класс должен выполнять какие действия для того, чтобы быть «хорошим уровнем» дизайна. Я бы хотел отделить уровни «лучшей практикой», но мне трудно понять, как функция PersonBAL.GetAll() будет возвращать данные, и если это действительно «unLINQed» элементы, поскольку это может быть веб-сервис, запрашивающий данные + как h *** мы сохраняем объект/ID для сохранения/обновления при возврате GUI-уровня? – BerggreenDK

+0

@Berggreen: Я уверен, что я ответил на этот вопрос; код lazy-loading идет в самой коллекции или в getter (если это ассоциация 1: 1). Если вы пытаетесь разоблачить этот тип API через веб-службу, вы делаете это неправильно; веб-службы выставляют операции, а не данные. Сказав, что для тех редких случаев, когда вам нужно возвращать глубоко вложенные отношения через веб-службу, типичным решением является позволить потребителю указать в запросе, какие ассоциации загружать, а остальные оставить как «null» '/ empty (без ленивой загрузки). – Aaronaught

+0

хорошо, я мог бы просто не понять ваш ответ полностью, но тогда я буду отмечать его как ответ. : o) Еще раз спасибо !! – BerggreenDK

Смежные вопросы