#c# #linq-to-sql #design-patterns #dependency-injection
#c# #linq-to-sql #шаблоны проектирования #внедрение зависимостей
Вопрос:
Я рефакторингую свое приложение, чтобы оно было менее зависимым от источника данных (на данный момент я использую Linq To Sql). Но мне нравится, как Linq To Sql генерирует мои классы из моей базы данных и как он отслеживает изменения.
Если бы это был не Linq, я бы просто обернул класс интерфейсом, а затем позволил моему бизнес-уровню зависеть от этого интерфейса. Однако я не могу сделать это с помощью linq.
Итак, допустим, у меня есть репозиторий, IFooRepository
где Foos
находится таблица в базе данных, и Linq сгенерировал класс Foo
для меня. Если бы я не беспокоился о зависимостях, я бы просто вернул объект linq Foo
. Но мой уровень бизнес-логики не имеет понятия о моем уровне Linq, поэтому я не могу внедрить эти объекты в свой BLL. И поскольку мои объекты Linq не могут реализовать какой-либо интерфейс, у меня не может быть никаких функций в IFooRepository, возвращающих IFoo
реализацию.
Итак, я хочу, чтобы мой BLL обрабатывал объекты Linq, но не зная об этом, чтобы мой уровень Linq отслеживал изменения BLL. Возможно ли это? Я думаю о том, чтобы просто наследовать класс от объекта Linq, а затем использовать его для передачи. Было бы это допустимо?
Ответ №1:
Ваши объекты LINQ-to-SQL могут реализовывать интерфейсы, и вы можете добавлять к ним любую функциональность, которая вам нравится. Созданные объекты являются partial
классами, поэтому вы можете сделать что-то похожее на это в другом файле, если это часть вашей сборки LINQ-to-SQL:
public partial class YourEntityType : IInterfaceName
{
// your implementation
}
Вам просто нужно определить контракты в другой сборке, на которую ссылается как сборка LINQ-to-SQL, так и сборка бизнес-логики.
Комментарии:
1. Да, сущности могут реализовывать интерфейс. Но как вы заставите работать поддержку запросов LINQ?
2. @Steven: Я не уверен, о чем вы спрашиваете; реализация интерфейса не повлияет на возможность составления запроса. Мысль OP заключалась в том, что, поскольку его сущности не могут реализовать пользовательский интерфейс, он не может использовать репозиторий. Поскольку это не так, я думаю, что это решает вопрос.
3. @Adam: OP хочет иметь возможность использовать эти объекты в запросах LINQ. Конечно, вы все еще можете запускать в памяти запросы LINQ (к объектам) к этим объектам. Однако LINQ to SQL просто не имеет понятия, что делать, когда вы запрашиваете
IQueryable<IInterfaceName>
. Это просто не сработает. Вам нужно работать сYourEntityType
в BLL, чтобы иметь возможность выполнять сложные запросы LINQ (которые выполняются внутри базы данных).4. @Steven: OP никогда ничего не говорил о том, что требуется возможность запроса, и, похоже, не является разумным предположением, что он ожидал этого.
5. @Adam: Я читаю здесь между строк, но на самом деле, он явно не сказал, что хочет этого.
Ответ №2:
Это, безусловно, возможно, особенно с LINQ to SQL. Здесь вам нужно сделать две вещи:
- Используйте объекты POCO (смотрите здесь и здесь для автоматизации T4).
- Скрыть
DataContext
за абстракцией.
Удачи.