使用Entity Framework Core更新相关数据 [英] Updating related data with Entity Framework Core

查看:61
本文介绍了使用Entity Framework Core更新相关数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Entity Framework Core构建了一个简单的webapi.我正在使用模型和视图模型来管理客户端实际接收的数据.这是我创建的模型和视图模型:

Im building a simple webapi with Entity Framework Core. I am using models and viewmodels to manage what data the client is actually receiving. Here's the models and viewmodels i created:

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方法:

Now for updating i created a Update method in my controller:

[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);
}

我陷入了如何更新连接到团队的TeamAgent的问题上.我尝试和工作的一件事是删除所有TeamAgent,然后在每次团队数据更新时都创建新的.方法如下:

I got myself stuck at the problem how to update the TeamAgents connected to the Team. One thing what i tried and worked was deleting all the TeamAgents and then just creating new ones every time Team data is updated. Here's how:

team.TeamAgents.Clear();
await _context.SaveChangesAsync();
team.TeamAgents.AddRange(teamVM.TeamAgents);

_context.Teams.Update(team);
await _context.SaveChangesAsync();

但这显然不是很好的方法.用Entity Framework Core更新相关项目的正确方法是什么?

But this clearly is not very good way to do it. What is the right way to update the related items with Entity Framework Core?

推荐答案

Julie Lerman在她的文章从EF开始处理2016年4月EF中的断开连接实体状态.如果您还没有看过这篇文章,那么非常值得一读.可悲的是,自EF Core 2.0起,仍然没有内置的方法来更新对象图.

Julie Lerman addresses this in her article Handling the State of Disconnected Entities in EF from April of 2016. If you haven't seen the article it is well worth the read. Sadly, as of EF Core 2.0 there is still no built in way to update object graphs.

朱莉(Julie)文章中提到的方法是通过向对象添加属性并将状态发送给客户端来基本上跟踪分离实体的状态.客户端可以修改状态并将其发送回服务器,然后您当然可以使用该信息来做正确的事情.

The approach mentioned in Julie's article is to basically track the state of the detached entities by adding a property to your objects and sending the state along to the client. The client can modify state and send that back to the server, and then of course you can use that information to do the right thing.

在我最近的项目中,我采用了略有不同的方法,主要是因为到目前为止只有一个操作需要更新子集合.在必须再次执行此操作时,我可能会考虑朱莉的建议并进行重构.

In my most recent project I've taken a slightly different approach mainly due to only having one operation so far that needs to update a child collection. At the point which I have to do this again, I'll probably take Julie's suggestions to heart and refactor.

基本上,这只是一个手动的对象图更新,看上去与EF 6.0所采用的方法非常相似.需要注意的一件事是,现在使用EF Core,您可以调用传递实体的Remove(),而不必关心它所属的dbSet.

Basically it's just a manual object graph update, which looks pretty similar to the approach you'd take with EF 6.0. One thing to note is that now with EF Core you can just call Remove() passing the entity, not having to care what dbSet it belongs to.

/// <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();
}

这篇关于使用Entity Framework Core更新相关数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆