LINQ к веб-приложению SQL лучшие практики

По моему опыту, создавая веб-приложения, я всегда использовал подход n-tier. DAL, который получает данные из дб и заполняет объекты, и BLL, который получает объекты от DAL и выполняет любую бизнес-логику, требуемую на них, и веб-сайт, который добирается, это - данные дисплея из BLL. Я недавно начал изучать LINQ, и большинство примеров показывает запросы, происходящие прямо от кода-веб-приложения-behinds (возможно, что я только видел чрезмерно упрощенные примеры). В n-tier архитектуре это всегда рассматривалось как большое нет - нет.
Я немного не уверен в том, как спроектировать новое веб-приложение. Я использовал Проводник Сервера и dbml разработчика в VS2008 для создания dbml и объектных отношений. Кажется немного неясным мне, если dbml считали бы уровнем DAL, если бы веб-сайт должен назвать методы в BLL, который затем сделал бы запросы LINQ и т.д.
Каковы некоторые лучшие практики общей архитектуры или подходы к созданию решения для веб-приложения с помощью LINQ для SQL?

14
задан derek 7 May 2010 в 01:19
поделиться

2 ответа

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

Я всегда стараюсь предотвратить утечку LINQ to SQL DataContext на уровень представления (ваше веб-приложение). Таким образом, он не должен иметь возможность создавать или фиксировать DataContext . Вы также не должны возвращать объекты IQueryable на уровень представления. ИМО, бизнес-уровень должен иметь полный контроль над временем существования DataContext (единица работы) и формой SQL-запросов.

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

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

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

Чтобы решить эту проблему, необходимо вернуть объекты передачи данных (DTO) из BL на уровень представления. DTO будет содержать только данные и без внутреннего DataContext , а также без ленивых загружаемых свойств. DTO может быть специально отформатирован для текущего запроса. DTO, конечно, сами по себе приводят к накладным расходам на кодирование, поэтому размер вашей системы и потребности в производительности должны это оправдывать. Чтобы упростить себе задачу, я обычно помещаю методы статической проекции в DTO. Хотя это не соответствует принципу разделения ответственности , я считаю, что это очень практичное решение. Взгляните, например, на этот 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 DTO. Это значительно упрощает преобразование объектов домена в 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 выполнять всю операцию в базе данных.

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

16
ответ дан 1 December 2019 в 13:08
поделиться

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

4
ответ дан 1 December 2019 в 13:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: