Linq To Sql - Выполнение динамического поиска уровня приложения без предоставления уровня DAL как DLL

Linq to SQL, C#.

У меня 3 слоя: DAL,BL, Аппликация. Я хочу построить функции поиска в BL для каждой таблицы, чтобы эти функции получали в качестве параметра выражение "где" из прикладного уровня. Преимущество в этом подходе - одна функция для каждой таблицы, так что клиент может искать в свободном и динамичном режиме, давая ему 5 (например) способов; ограничить его поиск.

Для этого мне нужно дать моему прикладному уровню DLL моего уровня DAL. Это не является хорошим подходом к решению проблемы (предоставление пользователю возможности динамически создавать поиск, ограничив его встроенными функциями поиска). Если уровень приложения имеет DLL для моего уровня DAL, уровень Aplication может объявить ContextObject и делать плохие вещи для моей базы данных.

Что я могу сделать для решения этой проблемы?

Большое спасибо, Став Альфи.

Обновление 1:

Как вы знаете, Linq to Sql создает класс для каждой таблицы. Я не хочу выставлять DAL DLL на прикладном уровне, поэтому я не могу использовать Linq для классов Sql на прикладном уровне. Решение, которое я нашел, состоит в том, чтобы создавать классы, которые выглядят одинаково с классами Linq to Sql, чтобы уровень приложений мог их использовать. Слой BL является resposnibol для проведения этих классов. Исходя из того факта, что прикладной уровень не использует Linq для классов Sql, я не могу дать прикладному уровню IQueryable (любой результат функции Any уровня BL преобразуется в классы прикладного уровня).

Обновление 2:

У Linq to Sql есть LinqClientDB.designer.cs, и он создает эти классы

[global::System.Data.Linq.Mapping.DatabaseAttribute(Name="ClientDB")]
public partial class LinqClientDBDataContext : System.Data.Linq.DataContext

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Clients")]
public partial class Client : INotifyPropertyChanging, INotifyPropertyChanged

Если я предоставляю уровень DAL уровню приложения, уровень приложения может иметь доступ к классу LinqClientDBDataContext. это не очень хороший подход. Таким образом, в слое BL я конвертирую класс DAL.Client в класс BL.Client, но тогда у меня не может быть динамического поиска по таблице клиента. Что я могу сделать?

2 ответа

Решение

Разоблачение IQueryable<T> через ваш BL не выставляет ваш DAL. Поскольку вы хотите инкапсулировать объекты базы данных в отдельные классы для уровня приложения, вы все равно можете сделать это, хотя приложение будет более ограничено в типах запросов, которые оно может запускать.

// DAL
public class Entity { ... }

// BL
public class EntityInfo : Entity { ... }

...

public IQueryable<EntityInfo> GetEntities()
{
    return from e in dbContext.Entities
           select new EntityInfo
           {
               // populate your application layer object
           }
}

Вот альтернативный способ его кодирования, который дает тот же результат

public Expression<Func<Entity, EntityInfo>> materializeEntityInfo =
    e => new EntityInfo { .. };

public IQueryable<EntityInfo> GetEntities()
{
    return dbContext.Entities.Select(materializeEntityInfo);
}

Вы можете сделать контекстный класс internal в то время как классы сущностей public,

Это позволит вам создавать классы обслуживания в вашем DAL, которые возвращают классы сущностей (как IEnumerables) из контекста, который не предоставляется клиенту.

Хотя это действительно так, часто желательно (как сказал pswg) иметь DTO или просматривать объекты модели, доступные клиенту (или прикладному уровню), потому что это абстракция DAL.

Другие вопросы по тегам