Как создать анонимный объект из T?

У меня есть метод GetEntities в контексте EF. В некоторых случаях я не хочу загружать в память все свойства сущностей. Я хочу загрузить только «выбранные» свойства. Я использую анонимный объект для получения только специальных свойств. Например, у меня есть объект Product, и я получаю только свойства Name и Cost (ТОЛЬКО ДЛЯ ЧТЕНИЯ).

context.GetEntities<Product>().Select(a => new { a.Name,a.Cost }).ToList();

Я использую его во многих местах. Итак, я создал коллекцию PropertyNames и хочу создать метод GetEntities, который получает сущности со следующими свойствами:

 public object GetEntities<T>(IEnumerable<string> proeprtyNames) 
 {
     return //anonymous entities which have only proeprtyNames properties
 }

Как создать этот метод? А также я не знаю, какой должен быть возвращаемый тип метода

Вы не можете определить анонимный тип в качестве возвращаемого типа. Возможно, вы сможете вернуть динамический тип, но это не совсем безопасное программирование типов. Я думаю, вы должны просто написать этот код прямо в своей логике, этот метод на самом деле вас ничего не спасет.

Metheny 26.04.2019 08:17

Я бы не поступил так, как ты собираешься. Однако, чтобы заставить его работать, вы должны заглянуть в System.Reflection. Там вы можете получить доступ к свойствам как к коллекции.

Mike 26.04.2019 08:19
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
441
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать Шаблон репозитория для этой проблемы.

Создайте класс Repository как ;

public class Repository<T> where T : class
{
    private readonly DbContext _dbContext;
    private readonly DbSet<T> _dbSet;

    public Repository(DBContext dbContext)
    {
        _dbContext = dbContext;
        _dbSet = dbContext.Set<T>();
    }


    public IQueryable<T> GetAll()
    {
        return _dbSet;
    }
}

и ваша функция может быть

 public object GetEntities<T>() 
 {
     using (DBContext db = new DBContext())
     {
            Repository<T> repository = new Repository<T>(db);
            list = repository.GetAll();
            return list.ToList();
     }
 }
Ответ принят как подходящий

1) Вам необходимо создать репозиторий, чтобы принять ваш TEntity в качестве объекта универсального класса, и в этом репозитории вы должны создать один метод, который может извлекать только те столбцы из таблицы базы данных, которые вы указали в предикате выражения Select.

public class Repository<TEntity> where TEntity : class
{
    private readonly DbContext _context;

    public Repository(DbContext context)
    {
        _context = context;
    }

    public List<TResult> GetEntities<TResult>(Expression<Func<TEntity, TResult>> selector) where TResult : class
    {
        return _context.Set<TEntity>().Select(selector).ToList();
    }
}

2) И затем, используя вышеуказанный репозиторий, вы можете передавать только те свойства из вашего объекта Product, которые вы хотите получить, например

Repository<Product> repository = new Repository<Product>(new MySqlDbContext());

var anonymousResultSet = repository.GetEntities(x => new { x.Name, x.Cost });  //<= Here you can specify those columns that you want to retrieve.

return anonymousResultSet;

Как я могу получить другие сущности?

Dilshod K 26.04.2019 09:32

Не понял, что ты хочешь сказать?

er-sho 26.04.2019 09:32

Я не могу использовать селектор Expression<Func<TEntity, TResult>> в параметре. У меня есть только коллекция строк. Посмотрите на метод GetEntities выше

Dilshod K 26.04.2019 09:35

если имена ваших свойств находятся в строках, вам нужно отражение, потому что вам нужно сообщить компилятору, какое имя свойства сопоставляется со свойством сущности. Я думаю, что это утомительная задача. Я предлагаю вам просмотреть мой ответ, потому что шаблон репозитория более гибкий и подходит в большинстве случаев.

er-sho 26.04.2019 09:40

Что просходит? Вы столкнулись с какой-либо проблемой сейчас?

er-sho 27.04.2019 18:50

Как сказал Майк выше, вам действительно нужно использовать отражение, чтобы работать так, как вы предполагали, потому что компилятор не будет знать о ваших именах свойств строк, а отражение довольно сложно для выполнения вашей работы. Так что попробуйте, как я понял, это действительно полезно, и большинство разработчиков предпочитают этот подход.

er-sho 27.04.2019 18:57

Другие вопросы по теме