我知道标题不好。
我有一个包含我所有实体功能的服务。
在我的服务中,有一个具有这种结构的功能
IList<T> GetAllPaged<TKey>(
List<Expression<Func<T, bool>>> predicate,
Expression<Func<T, TKey>> orderKeySelector
);
此函数从一个实体获取数据并对其进行排序。
现在我想做更多。
首先从一个实体中进行选择,然后按顺序对其进行分组,最后从分组项目中选择新项目。
这样的事情:
IList<TReturn> GetAllPaged<TResult, TKey, TGroup, TReturn>(
List<Expression<Func<T, bool>>> predicate,
Expression<Func<T, TResult>> firstSelector,
Expression<Func<TResult, TKey>> orderSelector,
Func<TResult, TGroup> groupSelector,
Func<IGrouping<TGroup, TResult>, TReturn> selector
);
这可能吗?
答案 0 :(得分:3)
这是我认为你要求的解决方案。
首先,基础存储库。我已经创建了一个基础存储库,因为我希望你不会将这种疯狂暴露给应用程序而只暴露给存储库。
abstract class BaseRepo<TEntity>
{
// If you're using Entity Framework, this method could
// be implemented here instead.
protected abstract IQueryable<TEntity> Entities { get; }
protected IList<TReturn> GetAllPaged<TResult, TKey, TGroup, TReturn>(
List<Expression<Func<TEntity, bool>>> predicates,
Expression<Func<TEntity, TResult>> firstSelector,
Expression<Func<TResult, TKey>> orderSelector,
Func<TResult, TGroup> groupSelector,
Func<IGrouping<TGroup, TResult>, TReturn> selector)
{
return predicates
.Aggregate(Entities, (current, predicate) => current.Where(predicate))
.Select(firstSelector)
.OrderBy(orderSelector)
.GroupBy(groupSelector)
.Select(selector)
.ToList();
}
}
然后执行。
class HorseRepo : BaseRepo<Horse>
{
// This will of course be some data source
protected override IQueryable<Horse> Entities
{
get
{
return new List<Horse> {
new Horse { Id = 1, Name = "Mr Horse", Color = "Brown" },
new Horse { Id = 2, Name = "Mrs Horse", Color = "White" },
new Horse { Id = 3, Name = "Jr Horse", Color = "White" },
new Horse { Id = 4, Name = "Sr Horse", Color = "Black" },
new Horse { Id = 5, Name = "Dr Horse", Color = "Brown" },
}.AsQueryable();
}
}
// This is what I think you should expose to the application
// This is the usage of the expression fest above.
public IEnumerable<GroupedHorses> GetGroupedByColor() {
return horseRepo.GetAllPaged(
new List<Expression<Func<Horse, bool>>> {
h => h.Name != string.Empty,
h => h.Id > 0
},
h => new HorseShape { Id = h.Id, Name = h.Name, Color = h.Color },
hs => hs.Name,
hs => hs.Color,
g => new GroupedHorses
{
Color = g.Key,
Horses = g.ToList()
}
);
}
}
需要一些课程:
class GroupedHorses
{
public string Color { get; set; }
public IList<HorseShape> Horses { get; set; }
}
class HorseShape
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
}
// Define other methods and classes here
class Horse
{
public int Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public string UninterestingProperty { get; set; }
}
答案 1 :(得分:2)
也许你可以传递一个与你的实体做某事的通用函数? 我知道表达式很有趣,但你应该总是考虑最终结果是否比简单的更好。
这样的事情:
TResult Query<TEntity, TResult>(Func<IQueryable<TEntity>, TResult> queryFunction)
实体框架的实施:
using(var context = new SomeContext())
{
return queryFunction(context.Set<TEntity>());
}
用法:
var listOfCars = carService.Query(cars => cars
.Select(c => new { Id = c.Id, Name = c.Name }) // c stands for car
.GroupBy(a => a.Name) // a stands for "anonymous object"
.OrderBy( /* order your group in some fashion */)
.ToList()
);
如果将所有这些逻辑放在单独的参数中,您将失去使用匿名对象的能力,您将发现自己编写了许多服务方法。