Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Linq(到EF或SQL)中组合多个重构的Select表达式?_Linq_Linq To Entities - Fatal编程技术网

如何在Linq(到EF或SQL)中组合多个重构的Select表达式?

如何在Linq(到EF或SQL)中组合多个重构的Select表达式?,linq,linq-to-entities,Linq,Linq To Entities,假设我有这个视图模型: public class SeriesLinkViewModel { public static Expression<Func<Series, SeriesLinkViewModel>> FromSeries = s => new SeriesLinkViewModel { Name = s.Name, Slug = s.Slug, };

假设我有这个视图模型:

public class SeriesLinkViewModel
{
    public static Expression<Func<Series, SeriesLinkViewModel>> FromSeries =
        s => new SeriesLinkViewModel
        {
            Name = s.Name,
            Slug = s.Slug,
        };

    public string Name { get; set; }
    public string Slug { get; set; }
}
太棒了。但是如果我想添加到这个查询中,我该怎么做?假设我还想从表中提取一个描述列。通常,我可以选择一个新的{}并将描述放在那里,但我不能这样做,因为我只能在`.select中放一个投影函数

我希望我能做这样的事情:

q = from s in dc.Series
    select new
    {
        Series = SeriesLinkViewModel.FromSeries.Compile()(s),
        Description = s.Description
    };
但我有一个例外:

System.InvalidCastException:无法删除 类型的强制转换对象 'System.Linq.Expressions.FieldExpression' 打字 'System.Linq.Expressions.LambdaExpression'


或者我至少可以在一次往返中完成所有这些查询吗?我知道TransactionScope可以用于进行更改,但我认为它不会导致查询一次完成。

我知道这并不完全是您想要的,但一个可能的解决方法是创建这样的方法

private IQueryable<SeriesLinkViewModel> FromSeries(IQueryable<Series> seriesQuery)
{
    return from s in seriesQuery
           select new SeriesLinkViewModel
           {
                Name = s.Name,
                Slug = s.Slug
           };
}
这并不理想,因为您没有创建可与其他表达式组合的可重用表达式,但至少您只有一个映射函数,所有类似的查询都可以通过该函数运行。

解决了这一问题:


这是对Rei答案的补充,我将其标记为正确。如果要删除对局部变量的依赖,请查看。

我认为这是一个更好的解决方案

public class SeriesLinkViewModel
{
    public static Expression<Func<Series, SeriesLinkViewModel>> FromSeries =
        s => new SeriesLinkViewModel
        {
            Name = s.Name,
            Slug = s.Slug,
        };

    public string Name { get; set; }
    public string Slug { get; set; }
}

public class SeriesLinkExtendedViewModel: SeriesLinkViewModel
{
    public new static Expression<Func<Series, SeriesLinkExtendedViewModel>> FromSeries = 
        SeriesLinkViewModel.FromSeries.Merge(s => new SeriesLinkExtendedViewModel
        {
            Description = s.Description
        });

    public string Description { get; set; }
}

// Somewhere else...
var q = from s in dc.Series.Select(SeriesLinkExtendedViewModel.FromSeries);
合并扩展方法将返回一个投影,该投影是合并两个投影表达式的结果,因此包含三列:Name、Slug和Description


实际实现可以在以下链接中找到:

我不确定您遇到了什么问题。为什么不将Description列添加到SeriesLinkViewModel,或者创建一个包含Description的新ViewModel类呢?这是一个过于简单的示例。问题是当我有更多的查询组合要做时。然后,我可以做真正的大范围查询,检索大量的内容,或者我有大量的ViewModels,除了我不能编写一个精明的查询之外,没有什么特别好的理由。我想我遗漏了一些东西-这与仅仅传递一个表达式有什么不同。选择?我认为它也不应该有什么不同。。。。但是linq实现中的某些东西意味着它不能将投影表达式合并到查询中。
return FromSeries(from s in Series
                  where s.Name == "foo"
                  select s);
var fs = SeriesLinkViewModel.FromSeries; //needs to be local for some reason
q = from s in dc.Series.AsExpandable() //enables LinqKit to do its magic
    select new
    {
        Series = fs.Invoke(s), //and voila!
        Description = s.Description
    };
public class SeriesLinkViewModel
{
    public static Expression<Func<Series, SeriesLinkViewModel>> FromSeries =
        s => new SeriesLinkViewModel
        {
            Name = s.Name,
            Slug = s.Slug,
        };

    public string Name { get; set; }
    public string Slug { get; set; }
}

public class SeriesLinkExtendedViewModel: SeriesLinkViewModel
{
    public new static Expression<Func<Series, SeriesLinkExtendedViewModel>> FromSeries = 
        SeriesLinkViewModel.FromSeries.Merge(s => new SeriesLinkExtendedViewModel
        {
            Description = s.Description
        });

    public string Description { get; set; }
}

// Somewhere else...
var q = from s in dc.Series.Select(SeriesLinkExtendedViewModel.FromSeries);