Это немного сложно объяснить, поэтому проще всего использовать пример.
Я пытался выполнить Fun c в Fun c, но он не поддерживается Linq to Entities.
Итак, сначала, что работает ...
internal class CategoryHolder<T>
{
public int FamilyId { get; set; }
public T CategoryData { get; set; }
}
public class StatusFilterData
{
public string Status { get; set; }
public bool HasOutcomes { get; set; }
}
public List<FollowUpsCategoryStatistics<StatusFilterData>> GetFollowUpIdsGroupedByFamily(int teamMemberId)
{
Expression<Func<FollowUp, CategoryHolder<StatusFilterData>>> groupingKey = fup =>
new CategoryHolder<StatusFilterData>()
{
FamilyId = fup.Family.Id,
CategoryData = new StatusFilterData
{
Status = fup.Status.ToString(),
HasOutcomes = fup.Campaign.FollowUpsOutcomes
.Any(outcome => outcome.ContactedMemberId == fup.Campaign.FollowUpsTeam.Id)
}
};
//GetAssignedOpenFollowUps returns IQueryable<FollowUp> which from EF: DbSet<FollowUp>
var doubleGroups = GetAssignedOpenFollowUps(teamMemberId)
.GroupBy(groupingKey)
.GroupBy(g => g.Key.CategoryData)
.ToList();
[...code removed for brevity]
}
Это довольно просто. Чтобы получить правильные группировки и связанные с ними числа и т. Д. c., Мне нужно дважды сгруппировать данные, сначала используя FamilyId и CategoryData, а второй раз просто CategoryData. Первая группировка всегда будет использовать FamnilyId, но тип CategoryData generi c, который используется как в 1-й, так и во 2-й группировках, может измениться (в приведенном выше примере это объект StatusFilterData). Вышеупомянутое работает хорошо, и оно правильно дает результат, который мне нужен, но только для сценария, где CategoryData имеет тип StatusFilterData.
То, что я пытаюсь сделать, но не получается, - это создать CategoryHolder. CategoryData Dynami c путем преобразования функции в generi c и передачи Expression, чтобы я мог определить результат в вызывающем коде, таким образом:
private List<FollowUpsCategoryStatistics<FollowUpsServices.StatusFilterData>> GetStatusFilterData()
{
var currentUser = new SessionHelper().GetCurrentUser();
var result = _followUpsServices.GetFollowUpIdsGroupedByFamily(
currentUser,
fup => new FollowUpsServices.StatusFilterData
{
Status = fup.Status.ToString(),
HasOutcomes = fup.Campaign.FollowUpsOutcomes
.Any(outcome => outcome.ContactedMemberId == fup.Campaign.FollowUpsTeam.Id)
}
);
return result;
}
public List<FollowUpsCategoryStatistics<TReturn>> GetFollowUpIdsGroupedByFamily<TReturn>(
int teamMemberId,
Expression<Func<FollowUp, TReturn>> categoryDataFunc
)
{
Expression<Func<FollowUp, CategoryHolder<TReturn>>> groupingKey = fup =>
new CategoryHolder<TReturn>()
{
FamilyId = fup.Family.Id,
CategoryData = categoryDataFunc.Compile().Invoke(fup)
};
//GetAssignedOpenFollowUps returns IQueryable<FollowUp> which from EF: DbSet<FollowUp>
var doubleGroups = GetAssignedOpenFollowUps(teamMemberId)
.GroupBy(groupingKey)
.GroupBy(g => g.Key.CategoryData)
.ToList();
[...code removed for brevity]
}
Хотя компилятор с этим согласен , Linq to Entities не так, как Fun c в Fun c не поддерживается - проблема в categoryDataFunc.Compile().Invoke(fup)
с существующим выражением.
Я пытался найти, как создать дерево выражений, но, честно говоря, я борюсь и потратил часы на то, чтобы никуда не спешить, поскольку деревья выражений для меня в новинку, и, хотя есть несколько отличных примеров, я не могу понять, как применить какие-либо из них к мой конкретный c сценарий.
Если у кого-то есть знания и время, чтобы помочь, я был бы благодарен за помощь.
Ура,
Павел