Использование
- Visual Studio 2010
- .Net Framework 4
- C #
- Linq to Entities
Issue
Я хотел бы иметь возможность применять объектно-ориентированные принципы, такие как DRY и SOLID, к некоторым проекциям Linq.С помощью скомпилированных запросов или переданных параметров я могу до сих пор успешно применять их к остальной части Linq, но не в проекциях.
Пожалуйста, дайте мне знать, если это невозможно, и я должен выбрать один из моих альтернативных вариантов.решения (описанные ниже), если это возможно, то как, или если я что-то упустил, и есть другая альтернативная реализация, которая будет удовлетворять цели.
Подробности
На высоком уровне я быхотелось бы иметь возможность динамически управлять типом, используемым в проекции Linq, с помощью стандартного запроса Linq или CompiledQuery.Я использую Linq to Entities в своих примерах и в реальном коде, однако проблема должна быть применима к ядру Linq.
Ниже приведены упрощенные примеры, которые не являются динамическими и не решают проблему.Они исправлены, чтобы всегда использовать FooUser для каждого типа.Я хотел бы иметь возможность динамически контролировать тип пользователя, создаваемого в проекции, и все это будет основано на общем интерфейсе IUser.Это будет или может быть похоже на то, как я могу контролировать, какой тип фильтра запросов.
Альтернативные решения
Я пытаюсь соответствовать DRY, SOLID, а также стараюсь избегать использования enum для обработки, которая является типичным запахом кода.Однако во всех моих попытках и исследованиях мне, кажется, приходилось прибегать к одному из следующих решений:
Реализовать запрос для каждого типа, которые все одинаковы, кроме типа, по которому они фильтруютсяи тип, используемый в проекции.Хотя это нарушает DRY и OCP, я могу инкапсулировать это в одном классе и хранить их близко друг к другу как выполненные запросы.Это потребует, чтобы класс изменился, если я добавлю новый тип или если вы запросите изменения данных.
Реализуйте перечисление с типами и используйте более обобщенный класс Userэто имеет свой тип как свойство.Однако из-за этого мне придется использовать enum в нескольких местах и вводить длинные операторы case для их обработки, чего я бы хотел избежать.
Я бы не хотел выбиратьмежду различными пороками, и имеют реализацию, которая может соответствовать всем принципам SOLID и DRY.Однако, если мне нужно, я думаю, что в итоге получу первую или ее версию.
Примеры
Стандартный простой запрос Linq
using (MyEntities context = new MyEntities())
{
var results = from u in context.Users
where u.UserType == type
select new FooUser
{
Id = u.UserID,
Name = u.UserName,
Location = u.UserLocation
};
}
Скомпилированная версия вышеприведенногоЗапрос
private static readonly Func<MyEntities, int, IQueryable<FooUser>> query = CompiledQuery.Compile<MyEntities, int, IQueryable<FooUser>>(
(context, type) => from u in context.Users
where u.UserType == type
select new FooUser
{
Id = u.UserID,
Name = u.UserName,
Location = u.UserLocation
});-