#c# #entity-framework-core #automapper
#c# #сущность-фреймворк-ядро #automapper
Вопрос:
У меня есть конечная точка API примерно так:
[HttpGet("{shoppingCartId}")]
public async Task<IActionResult> GetShoppingCart(int shoppingCartId)
{
var shoppingCart = await context.ShoppingCarts.Include(c => c.ShoppingCartItems).SingleOrDefaultAsync(c => c.Id == shoppingCartId);
if (shoppingCart == null)
return NotFound("There is no shoppingCart for specified query.");
return Ok(shoppingCart);
}
Это работает нормально. Возвращает ShoppingCart с ShoppingCartItems, как и ожидалось.
Но я не хочу возвращать ShoppingCart, а shoppingCartResource. Что-то вроде этого:
[HttpGet("{shoppingCartId}")]
public async Task<IActionResult> GetShoppingCart(int shoppingCartId)
{
var shoppingCart = await context.ShoppingCarts.Include(c => c.ShoppingCartItems).SingleOrDefaultAsync(c => c.Id == shoppingCartId);
if (shoppingCart == null)
return NotFound("There is no shoppingCart for specified query.");
var shoppingCartResource = mapper.Map<ShoppingCart, ShoppingCartResource>(shoppingCart);
return Ok(shoppingCartResource);
}
Как вы можете видеть, модель ShoppingCart содержит коллекцию ShoppingCartItem внутри.
public class ShoppingCart
{
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public ICollection<ShoppingCartItem> ShoppingCartItems { get; set; }
public ShoppingCart()
{
ShoppingCartItems = new Collection<ShoppingCartItem>();
}
}
И вот модель ShoppingCartResource
public class ShoppingCartResource
{
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public ICollection<ShoppingCartItemResource> ShoppingCartItemResources { get; set; }
public ShoppingCartResource()
{
ShoppingCartItemResources = new Collection<ShoppingCartItemResource>();
}
}
Код отображения является:
CreateMap<ShoppingCart, ShoppingCartResource>();
CreateMap<ShoppingCartItem, ShoppingCartItemResource>();
Ошибки нет, но я получил единственный shoppingCartResource с пустым ShoppingCartItemResource.
Ответ №1:
Вам не хватает одной строки, указывающей AutoMapper, где из нее следует отображать ShoppingCartItemResources
, потому что соответствующее свойство в исходном объекте не имеет того же имени — ShoppingCartItems
, поэтому оно не будет работать автоматически. Просто добавьте это:
CreateMap<ShoppingCart, ShoppingCartResource>()
.ForMember(
dst => dst.ShoppingCartItemResources,
opts => opts.MapFrom(src => src.ShoppingCartItems));
CreateMap<ShoppingCartItem, ShoppingCartItemResource>();
Ответ №2:
По умолчанию AutoMapper следует соглашению об именовании, которое автоматически создает карту между исходным свойством и целевым свойством, если их имена совпадают, и вам не нужно ничего настраивать для этого. Но, если вам нужна карта между двумя свойствами и их имена не совпадают, тогда вам нужно явно определить конфигурацию для этой карты.
Оба ваших объекта ShoppingCartResource
и ShoppingCart
имеют свойства с именами Id
и DateCreated
, и поэтому они были сопоставлены автоматически.
Чтобы получить карту между вашими ICollection
свойствами —
- если вы хотите автоматическую карту, вы должны дать им соответствующее имя
- если вы хотите сохранить различие в именовании, вы должны явно определить конфигурацию для их сопоставления. Что-то вроде —
CreateMap<ShoppingCart, ShoppingCartResource>()
.ForMember(d => d.ShoppingCartItemResources, opt => opt.MapFrom(s => s.ShoppingCartItems));
CreateMap<ShoppingCartItem, ShoppingCartItemResource>();