У меня есть следующий метод. Я использую анонимную проекцию для фильтрации включений EF. Я узнал этот метод из этого BlogPost: http://thedatafarm.com/data-access/use-projections-and-a-repository-to-fake-a-filtered-eager-load/Как я могу реорганизовать этот метод с использованием анонимной проекции, чтобы быть более общим?
public IEnumerable<Entities.Nutrient> FindAllForSpecificLanguage(bool overridePossibleLogicalDelete)
{
using (var context = CreateObjectContext())
{
context.ContextOptions.LazyLoadingEnabled = false;
Entities.Nutrient[] result;
var list = context.Nutrients
.Select(nut => new
{
Entity = nut,
Descriptions = nut.Descriptions.Where(desc => desc.LanguageCode.Equals(DataLanguageContext.Current.DataLanguageCode))
}).ToList(); //perform query
var resultList = list
.Select(entity => entity.Entity);
return resultList;
}
}
Этот метод должен быть встроен во все услуги (API-интерфейс поддерживает около 30 языков, на данный момент у нас есть много накладных расходов DB ...). Я пытаюсь построить его в общем виде, но я ужасно неопытен в деревьях выражений. Я думал, что полностью воссоздал эту функцию, но мне что-то не хватает, потому что она не работает. Это то, что я до сих пор:
public virtual IEnumerable<TEntity> FindAllForSpecificLanguage(bool overridePossibleLogicalDelete, Expression<Func<TEntity, IEnumerable<object>>> selectEntityDescriptions)
{
using (var context = CreateObjectContext())
{
context.ContextOptions.LazyLoadingEnabled = false;
ObjectQuery<TEntity> queryObjectSet = GetObjectSet(context);
TEntity[] result;
Type anonType = new {Entity = default(TEntity), Descriptions = Enumerable.Empty<object>()}.GetType();
// (entityManagerBaseEntity) => new { Entity = entityManagerBaseEntity, Descriptions = selectEntityDescriptions(entityManagerBaseEntity) }
// 1) "(entityManagerBaseEntity) =>"
var pe = Expression.Parameter(typeof(TEntity), "entityManagerBaseEntity");
// 2) "selectEntityDescriptions(entityManagerBaseEntity)"
var exprFunc = Expression.Invoke(selectEntityDescriptions, pe);
// get constructor for anonymous type
var constructorInfo = anonType.GetConstructor(new[] { typeof(TEntity), typeof(IEnumerable<object>) });
// 3) "new AnonType(entityManagerBaseEntity, exprFunc(entityManagerBaseEntity))"
var constructAnonType = Expression.New(constructorInfo, pe, exprFunc);
// 4) combine all to a lambda
// {entity => new <>f__AnonymousType0`2(entity, Invoke(entity => entity.Descriptions.Where(desc => desc.LanguageCode.Equals(DataLanguageContext.Current.DataLanguageCode)), entity))}
var cooleExpression = Expression.Lambda<Func<TEntity, dynamic>>(constructAnonType, pe);
//var bla = cooleExpression.Compile();
//var list = queryObjectSet.AsQueryable().Provider.CreateQuery<dynamic>(cooleExpression).ToList();
var list = queryObjectSet.Select(cooleExpression).ToList(); //perform query
var resultList = list
.Select(entity => entity.Entity as TEntity);
return resultList;
}
}
(примечание: CreateObjectContext и GetObjectSet прекрасно методы работы)
который следовало бы назвать так:
_nutrientManager.FindAllForSpecificLanguage(true, (entity) => entity.Descriptions.Where(desc => desc.LanguageCode.Equals(DataLanguageContext.Current.DataLanguageCode)))
Выражение, которое будет построен набирается в комментариях. Я думаю, что это нормально, но соединение никогда не выполняется. Если я отладки я получаю следующую трассировку стека:
System.NotSupportedException: Только без параметров Конструкторы и Инициализаторы поддерживается в LINQ к Entities. в System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.NewTranslator.TypedTranslate (родитель ExpressionConverter, newExpression linq) в System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate (родитель ExpressionConverter , Expression LINQ)
Что такое $ в вашей консоли. WriteLine? Улучшено ли C#? –
Функция C# 6, для этих экспериментов мне нравится использовать VS2015 :-) просто хороший способ записи string.Format() – Yoeri
Я скажу! Больше не нужно перенумеровать элементы форматирования строки или помеченные заполнители формата! –