Бизнес-уровень, обрабатывающий Linq-объекты, не зная об этом?

#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. Здесь вам нужно сделать две вещи:

  1. Используйте объекты POCO (смотрите здесь и здесь для автоматизации T4).
  2. Скрыть DataContext за абстракцией.

Удачи.