在 EF Core 5 中保存相关数据(多对多)而不获取实际记录
Save Related Data (Many to Many) in EF Core 5 without getting the actual records
我正在为午餐预订创建一个网络应用程序。
public class Food : BaseEntity
{
public int FoodId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
public string PhotoPath { get; set; }
public ICollection<Menu> Menus { get; set; }
/*public ICollection<LunchReservation> LunchReservations { get; set; } omit */
}
public class Menu : BaseEntity
{
public Menu()
{
DateCreated = DateTimeOffset.Now;
DateModified = DateTimeOffset.Now;
}
public int MenuId { get; set; }
[Column(TypeName = "date")]
public DateTime MenuDate { get; set; }
public bool IsPublished { get; set; }
public ICollection<Food> Foods { get; set; }
/*public ICollection<LunchReservation> LunchReservations { get; set; } omit */
}
一切正常,但是当我想创建一个可以包含 1 种或更多食物的菜单时,我收到错误消息。
这是我创建菜单的 Dto
public class MenuCreationDto
{
public int[] FoodIds { get; set; }
public string MenuDate { get; set; }
}
此代码无法保存。
var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();
Menu newMenu = new()
{
MenuDate = menuDateInGregorian,
Foods = foods
};
await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();
但是为了节省食物,这段代码是有效的,但我不想从数据库中获取食物来制作菜单。
var foods = _db.Foods.Where(f => menuCDto.FoodIds.Contains(f.FoodId)).ToList();
Menu newMenu = new()
{
MenuDate = menuDateInGregorian,
Foods = foods
};
await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();
如何在不从数据库中获取实际食物的情况下将菜单保存到数据库?
您可以像在您的非工作示例中那样使用伪造的(a.k.a.stub)实体
var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();
但在让 EF Core 添加父实体 (Menu
) 之前,您必须让它知道这些是“现有”实体,否则它将把它们视为“新”实体并尝试插入新 Food
条记录,而不是预期的链接。您可以通过将它们附加到上下文来做到这一点,这会将它们标记为已存在且未更改:
_db.AttachRange(foods);
其余代码将相同,但现在应该可以正常工作了。
我正在为午餐预订创建一个网络应用程序。
public class Food : BaseEntity
{
public int FoodId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
public string PhotoPath { get; set; }
public ICollection<Menu> Menus { get; set; }
/*public ICollection<LunchReservation> LunchReservations { get; set; } omit */
}
public class Menu : BaseEntity
{
public Menu()
{
DateCreated = DateTimeOffset.Now;
DateModified = DateTimeOffset.Now;
}
public int MenuId { get; set; }
[Column(TypeName = "date")]
public DateTime MenuDate { get; set; }
public bool IsPublished { get; set; }
public ICollection<Food> Foods { get; set; }
/*public ICollection<LunchReservation> LunchReservations { get; set; } omit */
}
一切正常,但是当我想创建一个可以包含 1 种或更多食物的菜单时,我收到错误消息。
这是我创建菜单的 Dto
public class MenuCreationDto
{
public int[] FoodIds { get; set; }
public string MenuDate { get; set; }
}
此代码无法保存。
var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();
Menu newMenu = new()
{
MenuDate = menuDateInGregorian,
Foods = foods
};
await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();
但是为了节省食物,这段代码是有效的,但我不想从数据库中获取食物来制作菜单。
var foods = _db.Foods.Where(f => menuCDto.FoodIds.Contains(f.FoodId)).ToList();
Menu newMenu = new()
{
MenuDate = menuDateInGregorian,
Foods = foods
};
await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();
如何在不从数据库中获取实际食物的情况下将菜单保存到数据库?
您可以像在您的非工作示例中那样使用伪造的(a.k.a.stub)实体
var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();
但在让 EF Core 添加父实体 (Menu
) 之前,您必须让它知道这些是“现有”实体,否则它将把它们视为“新”实体并尝试插入新 Food
条记录,而不是预期的链接。您可以通过将它们附加到上下文来做到这一点,这会将它们标记为已存在且未更改:
_db.AttachRange(foods);
其余代码将相同,但现在应该可以正常工作了。