我正在建立一个简单的webapi与实体框架核心。我使用模型和视图模型来管理客户端实际接收的数据。下面是我创建的模型和视图模型:
public class Team : BaseEntity
{
[Key]
public int TeamId { get; set; }
[Required]
public string TeamName { get; set; }
public List<TeamAgent> TeamAgents { get; set; }
}
public class TeamViewModel
{
[Required]
public int TeamId { get; set; }
[Required]
public string TeamName { get; set; }
[DataType(DataType.Date)]
public DateTime DateCreated { get; set; }
[DataType(DataType.Date)]
public DateTime DateModified { get; set; }
public List<TeamAgent> TeamAgents { get; set; }
}
public class TeamAgent : BaseEntity
{
[Key]
public int TeamAgentId { get; set; }
[ForeignKey("Agent")]
public int AgentId { get; set; }
[JsonIgnore]
public virtual Agent Agent { get; set; }
[ForeignKey("Team")]
public int TeamId { get; set; }
[JsonIgnore]
public virtual Team Team { get; set; }
[Required]
public string Token { get; set; }
}
public class TeamAgentViewModel
{
[Required]
public virtual AgentViewModel Agent { get; set; }
[Required]
public string Token { get; set; }
}现在为了更新,我在我的控制器中创建了一个Update方法:
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromBody]TeamViewModel teamVM)
{
if (ModelState.IsValid)
{
var team = await _context.Teams
.Include(t => t.TeamAgents)
.SingleOrDefaultAsync(c => c.TeamId == id);
team.TeamName = teamVM.TeamName;
// HOW TO HANDLE IF SOME TEAMAGENTS GOT ADDED OR REMOVED???
_context.Teams.Update(team);
await _context.SaveChangesAsync();
return new NoContentResult();
}
return BadRequest(ModelState);
}我陷入了如何更新连接到团队的TeamAgents的问题。我尝试和工作的一件事是删除所有的TeamAgents,然后在每次团队数据更新时创建新的。下面是操作步骤:
team.TeamAgents.Clear();
await _context.SaveChangesAsync();
team.TeamAgents.AddRange(teamVM.TeamAgents);
_context.Teams.Update(team);
await _context.SaveChangesAsync();但这显然不是一个很好的方法。使用实体框架核心更新相关项的正确方式是什么?
发布于 2017-11-06 04:03:57
朱莉·勒曼在她2016年4月的文章Handling the State of Disconnected Entities in EF中提到了这一点。如果你还没有看过这篇文章,这篇文章很值得一读。遗憾的是,从EF Core 2.0开始,仍然没有内置的方法来更新对象图。
Julie的文章中提到的方法基本上是通过向对象添加一个属性并将状态发送到客户端来跟踪分离实体的状态。客户端可以修改状态并将其发送回服务器,然后您当然可以使用该信息来执行正确的操作。
在我最近的项目中,我采取了稍微不同的方法,主要是因为到目前为止只有一个需要更新子集合的操作。在我不得不再次这样做的时候,我可能会把Julie的建议放在心上并进行重构。
基本上这只是一个手动的对象图更新,它看起来非常类似于你在EF 6.0中采取的方法。要注意的一件事是,现在使用EF Core,您可以只调用Remove()来传递实体,而不必关心它属于哪个dbSet。
/// <param name="entity"></param>
public override void Update(Group entity) {
// entity as it currently exists in the db
var group = DbContext.Groups.Include(c => c.Contacts)
.FirstOrDefault(g => g.Id == entity.Id);
// update properties on the parent
DbContext.Entry(group).CurrentValues.SetValues(entity);
// remove or update child collection items
var groupContacts = group.Contacts.ToList();
foreach (var groupContact in groupContacts) {
var contact = entity.Contacts.SingleOrDefault(i => i.ContactId == groupContact.ContactId);
if (contact != null)
DbContext.Entry(groupContact).CurrentValues.SetValues(contact);
else
DbContext.Remove(groupContact);
}
// add the new items
foreach (var contact in entity.Contacts) {
if (groupContacts.All(i => i.Id != contact.Id)) {
group.Contacts.Add(contact);
}
}
DbContext.SaveChanges();
}发布于 2020-12-17 16:59:06
这要归功于@Slauma。
public void Update(UpdateParentModel model)
{
var existingParent = _dbContext.Parents
.Where(p => p.Id == model.Id)
.Include(p => p.Children)
.SingleOrDefault();
if (existingParent != null)
{
// Update parent
_dbContext.Entry(existingParent).CurrentValues.SetValues(model);
// Delete children
foreach (var existingChild in existingParent.Children.ToList())
{
if (!model.Children.Any(c => c.Id == existingChild.Id))
_dbContext.Children.Remove(existingChild);
}
// Update and Insert children
foreach (var childModel in model.Children)
{
var existingChild = existingParent.Children
.Where(c => c.Id == childModel.Id && c.Id != default(int))
.SingleOrDefault();
if (existingChild != null)
// Update child
_dbContext.Entry(existingChild).CurrentValues.SetValues(childModel);
else
{
// Insert child
var newChild = new Child
{
Data = childModel.Data,
//...
};
existingParent.Children.Add(newChild);
}
}
_dbContext.SaveChanges();
}
}来源:
https://stackoverflow.com/questions/42735368
复制相似问题