Может ли AutoMapper.ProjectTo с EF Core обновить существующий объект

У меня есть существующий объект, который я хотел бы обновить с помощью последних данных из моей базы данных. В настоящее время я могу получить объект EF Core, а затем вызвать Mapper.Map для обновления своего dto. Есть ли способ использовать ProjectTo (или что-то подобное) для обновления моего объекта из базы данных?

Вместо этого:

var result = await context.DbSet
  .FirstOrDefaultAsync(e => e.Id == id, cancellationToken: cancellationToken)
  .ConfigureAwait(false);

return Mapper.Map(result, existingObject);

Как я могу:

var result = await context.DbSet
  .ProjectTo<TDest>(/* existingObject */)  // I tried .Map, but I got an error that automapper was trying to map this to a child object
  .FirstOrDefaultAsync(e => e.Id == id, cancellationToken: cancellationToken)
  .ConfigureAwait(false);

return existingObject;  // Where existingObject contains the latest database information

Это просто обновило объект EF из базы данных, когда я использую DTO с AutoMapper, я не сохраняю ссылку на исходный объект. Я могу получить последние данные из базы данных, я просто надеюсь, что есть способ обновить мой DTO непосредственно из запроса, а не отображать объект EF.

Matt Spinder 17.03.2022 16:04

Я бы попытался использовать DbSet.Select()

keuleJ 17.03.2022 16:37

Автосопоставитель карты. Он ничего не знает о базах данных или обновлениях. Он даже не нужен для работы с EF Core, он используется только для упрощения сопоставления длинных DTO базы данных с, например, DTO API на основе соглашений, выравнивания и т. д. ProjectTo(configuration) ожидает объект конфигурация, который указывает, как сопоставлять один DTO с другим.

Panagiotis Kanavos 17.03.2022 16:50

Почему вы пытаетесь изменить существующие объекты? Вы все равно загружаете объекты базы данных, почему бы их не использовать?

Panagiotis Kanavos 17.03.2022 16:54

PS: документация объясняет, для чего используется ProjectTo. Это также объясняет, что это должен быть последний вызов в запросе.

Panagiotis Kanavos 17.03.2022 17:16

@PanagiotisKanavos Спасибо за комментарии. Поэтому я должен: а) вызвать Where перед ProjectTo и не использовать фильтр в FirstOrDefault? б) Я исходил из того, что ProjectTo обходит создание объекта объекта и записывает непосредственно в dto, я ошибаюсь в этом? и в) то, на что я надеялся, не существует? Мне нужно будет получить объект сущности, а затем отобразить его, как я это делаю сейчас (мой первый пример)?

Matt Spinder 17.03.2022 17:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
6
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Не уверен, насколько это полезно, но вы можете использовать следующее расширение:

public static class MappingExtensions
{
    public static async Task<TDest> ProjectToObjAsync<TDest>(this IQueryable source, IMapper mapper, TDest obj, cancellationToken cancellationToken = default)
    {
        var loadedObj = await source.ProjectTo<TDest>(mapper.Configuration).FirstOrDefaultAsync(cancellationToken);

        if (loadedObj != null)
        {            
            mapper.Map(loadedObj, obj);
        }

        return obj;
    }
}

И использование:

var result = await context.DbSet
    .Where(e => e.Id == id)
    .ProjectToObjAsync(Mapper, existingObject, cancellationToken)
    .ConfigureAwait(false);

return existingObject;

@PanagiotisKanavos, как мне загрузить всю таблицу вызовом FirstOrDefaultAsync? Пожалуйста, начните читать, прежде чем оставлять комментарии.

Svyatoslav Danyliv 17.03.2022 17:04

Я неправильно понял, как работает ProjectTo. Это по-прежнему оставляет этот ответ не лучше, чем исходный код

Panagiotis Kanavos 17.03.2022 17:10

Заметил в первом предложении, что не вижу смысла в таком методе.

Svyatoslav Danyliv 17.03.2022 17:11

документы предостерегают от использования такого кодаProjectTo must be the last call in the chain. ORMs work with entities, not DTOs. So apply any filtering and sorting on entities and, as the last step, project to DTOs. Вот почему я предположил, что метод действительно выполняет результаты.

Panagiotis Kanavos 17.03.2022 17:12

@PanagiotisKanavos, даже хуже, я знаю, как ProjectTo работает внутри. Это использование правильно

Svyatoslav Danyliv 17.03.2022 17:21

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