说我有这个视图模型:
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; }
}
为了方便起见,我把投影功能放在那里,所以现在我可以这样说:
var links = dc.Series.Select(SeriesLinkViewModel.FromSeries);
真棒。但是,如果我想添加到此查询,该怎么办?假设我还要从表中提取Description
列。通常情况下,我可以做一个select new { }
并将Description
放在那里,但我不能那样做,因为我只能在`.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可以进行更改,但我认为它不会导致查询一次完成。
答案 0 :(得分:6)
用LinqKit:
解决了这个问题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
};
答案 1 :(得分:2)
这是Rei答案的补充(我标记为正确)。如果要删除对局部变量的依赖性,请查看this answer from Dan Abramov on how to fix LinqKit。
答案 2 :(得分:0)
我知道这不是你想要的,但一个可能的解决方法是创建一个像这样的方法
private IQueryable<SeriesLinkViewModel> FromSeries(IQueryable<Series> seriesQuery)
{
return from s in seriesQuery
select new SeriesLinkViewModel
{
Name = s.Name,
Slug = s.Slug
};
}
然后,当您想要使用投影时,请通过它运行查询。
return FromSeries(from s in Series
where s.Name == "foo"
select s);
不理想,因为你没有创建一个可以与其他人结合的可重用表达式,但至少你只有一个映射函数可以运行所有类似的查询。
答案 3 :(得分:0)
在我看来,这是一个更好的解决方案。
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。
可以在以下链接中找到实际的实施:https://coding.abel.nu/2013/01/merging-expression-trees-to-reuse-in-linq-queries/