2010-05-07 2 views
14

По моему опыту создания веб-приложений я всегда использовал подход n-уровня. DAL, который получает данные из db и заполняет объекты, и BLL, который получает объекты из DAL и выполняет любую требуемую бизнес-логику, и веб-сайт, который получает его данные отображения из BLL. Недавно я начал изучать LINQ, и большинство примеров показывают запросы, происходящие прямо из кода кода Web-приложения (возможно, я видел только упрощенные примеры). В n-уровневых архитектурах это всегда считалось большим нет-нет.
Я немного не уверен, как создать новое веб-приложение. Я использовал конструктор Server Explorer и dbml в VS2008 для создания связей dbml и объектов. Мне кажется немного непонятным, если dbml будет считаться слоем DAL, если веб-сайт должен вызывать методы в BLL, который затем будет выполнять запросы LINQ и т. Д.
Каковы некоторые общие рекомендации по архитектуре или подходы к создание решения для веб-приложений с использованием LINQ to SQL?Рекомендации по использованию веб-приложений LINQ to SQL

ответ

16

Боюсь, вы действительно видели слишком упрощенные примеры. LINQ to SQL (System.Data.Linq) - это ваш уровень DAL. Классы L2S генерируют ваш домен (но не путать с Domain-Driven Design). Кроме того, вы все равно можете написать свой бизнес-уровень.

Я всегда стараюсь предотвратить утечку LINQ в SQL DataContext в слой презентации (ваше веб-приложение). Поэтому он не должен создавать или фиксировать DataContext. Также вы не должны возвращать IQueryable<T> объектов на уровень презентации. IMO бизнес-уровень должен иметь полный контроль над временем жизни DataContext (единица работы) и формой SQL-запросов.

Однако есть несколько вариантов. Некоторые люди стремятся ослабить эти ограничения. Другие даже идут намного дальше. Это зависит от вашего вкуса и размера приложения. Чем больше приложение, тем больше оправдано добавление слоев абстракции.

При отказе IQueryable и других данных, связанных с оставлением бизнес-уровня, у вас возникнут некоторые интересные проблемы. Например, уровень представления должен проинструктировать бизнес-уровень, как сортировать результаты. Хотя вы можете позволить слою представления сортировать результаты сами, это означало бы, что вам нужно будет получить все данные из базы данных и страницы на уровне презентации, что приведет к очень плохо исполняющейся системе. Существует несколько решений этой проблемы. Во всех случаях вам нужно будет сообщить бизнес-уровню, как сортировать результаты для вас. Решения можно найти здесь, когда вы ищете LINQ dynamic sort. Я сам написал такое решение, here.

Еще одна проблема, которая запрещает IQueryable с момента выхода из вашего BL, заключается в том, что также объекты домена часто не могут оставить ваш BL. Большинство объектов домена LINQ to SQL будут содержать ленивые загруженные свойства (например, коллекции для других объектов домена). Однако, когда DataContext контролирует бизнес-уровень, он будет удален до того, как вы вернете результаты на уровень представления. Когда презентация, чем доступ к ленивому загруженному свойству, возникает исключение, поскольку DataContext уже был удален. Когда вы размещаете DataContext в своем бизнес-слое, это поведение, конечно, «по дизайну».Разрешение слоя представления на получение ленивых загруженных свойств означает, что BL теряет контроль над запросами, которые отправляются в базу данных, тем самым теряя контроль над производительностью.

Для решения этой проблемы вы должны вернуть объекты передачи данных (DTO) из BL в уровень презентации. DTO будет содержать только данные и нет внутренний DataContext, и никаких ленивых загруженных свойств. DTO может быть специально отформатирован для фактического запроса. Конечно, DTO приводят к чрезмерной нагрузке на кодирование, поэтому размер вашей системы и потребности в производительности должны ее оправдать. Чтобы облегчить для себя, я склонен ставить методы статической проекции на DTO. Хотя это не соответствует принципу separation of concerns, я считаю это очень практичным решением. Посмотрите, например, на этом CustomerDTO:

public class CustomerDTO 
{ 
    public int CustomerId { get; set; } 
    public string Name { get; set; } 
    // City is flatterned from Address.City. 
    public string City { get; set; } 

    internal static IQueryable<CustomerDTO> AsDTO(IQueryable<Customer> customers) 
    { 
     return 
      from customer in customers 
      select new CustomerDTO() 
      { 
       CustomerId = customer.Id, 
       Name = customer.Name, 
       City = customer.Address.City 
      }; 
    } 
} 

Это DTO определяет внутренний AsDTO метод, который способен преобразовать коллекцию Customer объектов предметной области в коллекцию CustomerDTO DTOS. Это значительно упрощает преобразование объектов домена в DTO. Посмотрите, например, в этом методе BL:

public static CustomerDTO[] GetCustomersByCountry(string country) 
{ 
    using (var db = ContextFactory.CreateContext()) 
    { 
     IQueryable<Customer> customers = 
      (from customer in db.Customers 
      where customer.Address.Country == country 
      orderby customer.Name, customer.Id); 

     return CustomerDTO.AsDTO(customers).ToArray(); 
    } 
} 

Хорошая вещь об этом подходе является то, что, когда вы смотрите на запрос SQL, вы увидите, что только идентификатор клиента, имя и город таблицы адресов будет извлекаться из базы данных. Это связано с тем, что метод AsDTO переводит один IQueryable в другой, позволяя LINQ to SQL выполнять полную операцию в базе данных.

Надеюсь, это дает некоторые идеи о том, что вы можете сделать. Конечно, это мой взгляд на предмет и то, что я нашел практичным в моих ситуациях.

+0

спасибо за тщательный ответ. Я сжимаюсь при выполнении доступа к данным на уровне презентации. Я обычно делаю большую часть моей сортировки на datalayer в настоящее время, так что это не проблема. Раньше я не слышал о DTO, звучит как-то, что нужно посмотреть дальше. – derek

+0

DTO часто считают, что у них много накладных расходов. Они особенно полезны при отправке данных через провод (например, при использовании веб-служб WCF или ASMX). Например, когда вы читаете «Microsoft .NET: Architecting Applications for the Enterprise» Дино Эспозито, вы заметите, что Dino считает, что обычно они приносят много накладных расходов, когда вы переносите объекты между слоями одного и того же AppDomain. Хотя он прав в этом, я все же нашел их полезными в этом конкретном сценарии, и я вижу, что накладные расходы становятся меньше, когда технология улучшается ... – Steven

+0

Например, новые конструкторы языка C#, такие как автоматические свойства, упрощают определение DTO и инструмент рефакторинга, такой как Refactor! Pro позволяет автоматически генерировать DTO из анонимного определения типа внутри запроса LINQ. – Steven

4

LINQ to SQL - это доступ к БД в реализации DAL, если вы хотите разделить между DAL и BLL. Если у вас менее сложное веб-приложение (а также никогда не предназначено для переключения бэкэндов БД), вы можете уйти без явного DAL/BLL и сделать все в коде. LINQ to SQL отлично работает для операций с readonly, но чувствует себя немного больше, чтобы реализовать операции записи.

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

  • Нет связанных вопросов^_^