我有一个数据库和一个映射到它的实体框架模型。该数据库有一个包含多列的“Products”表。在许多EF查询中,我只需要几列,我做一个投影,比如说
var projected = Context.Products
.Select(p => new ProjectedProduct { ProdID = p.ID, ProdTitle = p.Title })
.ToArray();
由于此投影多次使用,我将其移至单独的方法:
public static IQueryable<ProjectedProduct> ToProjectedProduct(this IQueryable<Product> query)
{
return query.Select(p =>
new ProjectedProduct { ProdID = p.ID, ProdTitle = p.Title });
}
所以我可以像以下一样使用投影:
var projected = Context.Products.ToProjectedProduct().ToArray();
现在我还想对单个产品实例使用相同的投影,例如:
var prod = Context.Products.First(p => p);
var projected = new ProjectedProduct { ProdID = prod.ID, ProdTitle = prod.Title });
我仍然希望使用相同的辅助方法进行投影,以便将它放在一个地方,但它不起作用,因为它只适用于IQueryable。我能做的是将投影转换为另一种方法,如
public static ProjectedProduct ToProjectedProduct(this Product p)
{
return new ProjectedProduct { ProdID = p.ID, ProdTitle = p.Title });
}
但现在这种方法不适用于IQueryable。我需要一个适用于这两种情况的辅助方法,我想要做的是:
var projected = Context.Products.Select(p => p.ToProjectedProduct()).ToArray();
但这不起作用,因为无法将辅助方法转换为数据库查询。
答案 0 :(得分:1)
使用Automapper。使用Automapper,您可以:
Mapper.CreateMap<Product, ProjectedProduct>
.ForMember(dto => dto.ProdID, m => m.MapFrom(p => p.ID))
.ForMember(dto => dto.ProdTitle , m => m.MapFrom(p => p.Title));
(ForMember
指定具有不同名称的属性之间的映射,Automapper自动映射具有相同名称的属性。)
现在您定义了可重复使用的投影。
稍后您可以这样做:
var projected = Context.Products.Project().To<ProjectedProduct>().ToArray();
Automapper被广泛使用,你会发现许多如何使用它的例子。
答案 1 :(得分:0)
IQueryable的select扩展方法需要Expression<Func<TSource, TResult>>
。这意味着我们可以在其他地方定义一个匹配此参数的对象,并将其传递给我们的select语句。
属性(也可以是方法):
public Expression<Func<Product, ProjectedProduct>> MapProduct
{
get
{
return p => new ProjectedProduct { ProdID = p.ID, ProdTitle = p.Title };
}
}
IQueryable用法:
var projected = Context.Products
.Select(MapProduct)
.ToArray();
单个实例用法:
var projected = Context.Products.Select(MapProduct).First();
IEnumerable usage:
// calling compile turns the expression into a normal Func
var projected = ProductList.Select(MapProduct.Compile());
普通对象用法:
var projected = MapProduct.Compile()(ProdObj);
MSDN IQueryable.Select - http://msdn.microsoft.com/en-us/library/bb534638(v=vs.100).aspx