Проблемы с выбором метода LINQ в интерфейсе Fluent - PullRequest
1 голос
/ 07 июля 2010

Я использую LINQ-to-Entities. Используя следующий запрос:

var x = from u in context.Users select new { u.Id, u.Name };

То, что только выбирает столбцы Id и Name. Отлично.

Я пытаюсь создать хранилище, которое можно передать этому new { u.Id, u.Name} в качестве параметра, позволяющего клиенту выбирать, какие столбцы используются в операторе SELECT.

Я пытаюсь использовать «свободный» интерфейс с моим хранилищем вместо синтаксиса запроса. По сути, последний вызов - преобразовать IQueryable в IList и выполнить код. Я посмотрел на библиотеку DynamicExpressions, но я не совсем уверен, что это путь, по которому я хочу пойти для этого. Это можно сделать с помощью синтаксиса запроса, но не с помощью свободного интерфейса?

Редактировать: Извините, я должен был упомянуть, что все запросы инкапсулированы внутри хранилища. Так, например, я хочу иметь возможность выставить метод, подобный следующему:

public void Project(Expression<Func<TEntity, TEntity>> fields)
{
    this.Projection = fields;
}

Так что назвать это будет так:

using (DBContext context = new DBContext())
{
    IUserRepository repo = new UserRepository(context);
    repo.Project(u => new { u.Id, u.Name });
    repo.GetById(100);
}

Внутри GetById будет что-то вроде ctx.Users.Where(u => u.Id == id).Select(this.Projection).

Таким образом, возвращаемые столбцы могут быть выбраны вызывающим кодом. Причина этого в том, что, возможно, я хочу вернуть объект User, но, возможно, мне нужны только Id и Name (и, следовательно, возвращать меньше данных по сети).

Проблема в том, что я, очевидно, не могу преобразовать анонимный тип в User. Было бы здорово, если бы я мог сделать что-то вроде:

repo.Project(u => new User() { Id = u.Id, Name = u.Name });

Что означало бы, что мне не нужно создавать анонимный тип. РЕДАКТИРОВАТЬ: Хорошо, похоже, это работает ТОЛЬКО, если тип, который возвращается является POCO ... тьфу.

EDIT2 : Возможно, мне придется пойти на подход DLINQ. Я думаю, что Expression<Func<TEntity, object>> (для использования анонимного типа), а затем использовать отражение, чтобы получить список свойств. Затем с помощью DLINQ создайте строковое выражение. Единственным недостатком является то, что я на самом деле не хочу использовать DLINQ, поскольку он добавляет немного накладных расходов (Reflection.Emit и т.

Ответы [ 2 ]

3 голосов
/ 07 июля 2010

Боюсь, я не совсем уверен, что вы на самом деле спрашиваете, но этот запрос легко написать с помощью точечной нотации (термин, который я использую для того, что я считаю, вы называете свободным интерфейсом):

var x = context.Users.Select(u => new { u.Id, u.Name });

Как говорит Адам, если вы пытаетесь создать что-то, что принимает этот кортеж как значение строго типизированным способом, вам понадобится именованный тип. Вы можете создать свой собственный, если вы используете .NET 4, вы можете использовать Tuple<T1, T2>.

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

РЕДАКТИРОВАТЬ: Хорошо, теперь у меня есть некоторые представление о том, что вы говорите ...

... вы должны заставить метод Project взять дерево выражений типа Expression<Func<TInput, TOutput>> и вернуть то, что использует TOutput - например, RepositoryProjection<TOutput>. Таким образом, анонимный тип по-прежнему эффективно фиксируется в вашем коде - так что вы можете использовать его позже (например, чтобы добавить дополнительное условие в запрос).

3 голосов
/ 07 июля 2010

Использование синтаксиса new без имени типа (как вы делаете) создает анонимный тип .Хотя они полезны, анонимные типы не могут быть представлены вне функции, которая их определяет.Если вам нужно передать эту конкретную сущность в другую функцию, вам нужно определить фактический класс с этими свойствами где-то в вашем коде и создать его экземпляр как часть запроса.Например:

public class MyUser
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Тогда:

var x = from u in context.Users select new MyUser { Id = u.Id, Name = u.Name }; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...