Подтвердить что ты не робот

Передача в выражение для linq Select

Это linq-to-sql

У меня много разных классов, которые выполняют один и тот же запрос, но немного проецируют результаты. В идеале я хотел бы иметь запрос в одном месте и проецировать проекцию в метод Select. Он отлично работает для конкретных типов:

public void GetResults() {
    var junk = db.SiteProducts.Select(Project());
}

public Expression<Func<DbEntities.SiteProduct, string>> Project() {
    return p => p.ProductAlert;
}

Но когда я пытаюсь вернуть анонимный тип, он терпит неудачу

public void GetResults() {
    var junk = db.SiteProducts.Select(Project());
}

public Expression<Func<DbEntities.SiteProduct, TResult>> Project<TResult>() {
    return p => new { p.ProductAlert };
}

Я полностью понимаю, почему во втором случае вывод типа не выполняется. Но есть ли трюк, способный выработать мои собственные выражения с самого начала - я не могу, чтобы это могло заставить это работать?

4b9b3361

Ответ 1

Если я правильно понял ваш вопрос, вы можете использовать этот код:

сначала объявите метод для выбора ваших данных следующим образом:

public List<TResult> FindAll<TResult>(Func<Regions, TResult> selector) where TResult : class
    {
        using (RepositoryDataContext = new DataClasses1DataContext())
        {
                return RepositoryDataContext.Regions.Select<Regions, TResult>(selector).ToList<TResult>();

        }
    }

тогда вы можете создать свой оператор select следующим образом:

Func<Regions, SelectAllRegion> select = r => new SelectAllRegion
        {
            RegionID = r.RegionID,
            RegionDescription = r.RegionDescription
        };

my SelectAllRegion:

 public class SelectAllRegion
{
    public SelectAllRegion()
    {
    }
    public int RegionID { get; set; }
    public string RegionDescription { get; set; }
}

и область Region таблица в northwing.I надеюсь, что это поможет вам

Ответ 2

IdeaBlade имеет класс ProjectionSelector, который вы можете использовать для абстракции ваших прогнозов. Когда вам нужно построить проекционный запрос, но вы не знаете типы, задействованные во время компиляции, вы можете создать экземпляр класса ProjectionSelector и передать информацию о типе во время выполнения.

Класс и код примера можно найти здесь:

Создать динамические предложения "Выбрать", "Выбрать много" и "Групповой"
http://drc.ideablade.com/xwiki/bin/view/Documentation/dynamic-projection

Ответ 3

Это не будет работать во время компиляции. Используя динамический материал, вы можете заставить его работать, конечно.

Простое решение - не использовать анонимный тип, а собственный класс DTO. Такой класс DTO занимает всего несколько строк и прост в обслуживании. Обычно это хорошее решение.

Ответ 4

Это интригующий вопрос. Я думаю, что DTO может помочь вам здесь, но есть ограничения и подводные камни, за которыми следует следить. Возьмите следующий LINQPad Пример:

class ProjectDTO
{
    public string Name { get; set; }

    public static Expression<Func<Project, ProjectDTO>> ToDTO = (e) => new ProjectDTO
    {
        Name = e.Name
    };

    public ProjectDTO() {}

    public ProjectDTO(Project project)
    {
        Name = project.Name;
    }
}

void Main()
{
    Projects.Select(p => p.Name).Dump();
    Projects.Select(ProjectDTO.ToDTO).Dump();
    Projects.Select(p => new ProjectDTO(p)).Dump();
}

SQL Сгенерировано:

SELECT [t0].[Name]
FROM [Project] AS [t0]
GO

SELECT [t0].[Name]
FROM [Project] AS [t0]
GO

SELECT [t0].[ProjectId], [t0].[Name], [t0].[Description], [t0].[DateCreated], [t0].[DateModified], [t0].[DateComplete], [t0].[CreatedBy]
FROM [Project] AS [t0]

Как вы можете видеть, вы не можете использовать конструктор-копир для назначения свойств DTO, поскольку это заставляет весь объект удаляться из базы данных.

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

Однако мне очень нравится второй вариант, но я уверен, что этот параметр, скорее всего, ограничивается однотипными проекциями, рассмотрим следующий пример:

var query = from p in Projects
            join t in Tasks on p.ProjectId equals t.ProjectId
            select ProjectDTO.ToDTO; //Can't be used like this

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

Без использования библиотеки Dynamic LINQ или создания дерева выражений вручную я также хотел бы увидеть, возможно ли с LINQ-SQL/LINQ-Entities создавать динамические выделения.