У меня есть общий репозиторий, который использует универсальные выражения для возврата данных из Entity Framework Core.
public async Task<T2> GetFieldsAsync<T2>(Expression<Func<T, T2>> expression)
{
return await context.Set<T>()
.Select(expression)
.FirstOrDefaultAsync();
}
Теперь, если я хочу выбрать определенные поля, во время компиляции я могу написать следующее утверждение:
var test = await _repositoryBase.GetFieldsAsync(x => new { x.Id, x.Name });
Я хочу иметь возможность делать выше во время выполнения вместо этого.Я могу создать выражение во время выполнения, которое возвращает один параметр следующим образом:
var expression = Expression.Parameter(typeof(Ingredient), "ingr");
var param1 = Expression.Property(expression, "Id");
var lambda = Expression.Lambda<Func<Ingredient, Guid>>(param1, expression);
var test = await _repositoryBase.GetFieldsAsync(lambda);
Вышеупомянутая лямбда-функция возвращает только одно свойство из класса Ingredient. Можно ли создать лямбду времени выполнения, которая возвращает анонимный объект, используя деревья выражений? Т.е.
x => new { x.Id, x.Name }
Обратите внимание, что пользователи могут запрашивать различные поля (например, Имя, Описание, DateCreated и т. Д.).) поэтому нужно динамически создавать лямбда-выражения.
Я знаю, что могу использовать https://github.com/StefH/System.Linq.Dynamic.Core для передачи строк для выбора операторов с помощью встроенных методов расширения IQueryable.Мне интересно, есть ли способ динамического выбора определенных полей во время выполнения через список полей, переданных пользователем.
В настоящее время мой подход заключается в получении всех свойств класса из базы данных и использовании ExpandoObject только для выбора полей, запрашиваемых пользователем.Проблема здесь в том, что хотя это работает, я возвращаю больше данных из базы данных, чем требуется.Я бы хотел избежать этого, выбрав только необходимые данные.
//user did not provide any fields so include all fields
if (string.IsNullOrEmpty(field))
{
myPropertyInfoList.AddRange(typeProperties);
}
else
{
foreach (var item in fields)
{
myPropertyInfoList.Add(type.GetProperty(item, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance));
}
var expandoObj = (IDictionary<string, object>)new ExpandoObject();
foreach (var item in myPropertyInfoList)
{
expandoObj.Add(item.Name, item.GetValue(ingrView));
}