EF5代码先用的ASP.NET Web API:与更新实体许多一对多的关系(EF5 code fir

2019-09-03 15:48发布

我试图更新Customer使用的ASP.NET Web API和Entity Framework 5码,第一我的数据库,但它不工作。 我的单位是这样的:

public class CustomerModel
{
    public int Id { get; set; }
    public string Name { get; set; }

    // More fields

    public ICollection<CustomerTypeModel> CustomerTypes { get; set; }
}

public class CustomerTypeModel
{
    public int Id { get; set; }
    public string Type { get; set; }

    [JsonIgnore]
    public ICollection<CustomerModel> Customers { get; set; }
}

没有什么特殊。 我已经建立了一个网络接口,用户可以通过提供的名称和检查一个或多个客户类型添加客户。 当打提交按钮,将数据发送到我的Web API方法:

public void Put([FromBody]CustomerModel customer)
{
    using (var context = new MyContext())
    {
        context.Customers.Attach(customer);
        context.Entry(customer).State = EntityState.Modified;
        context.SaveChanges();
    }
}

这将更新客户领域,但相关的客户类型都被忽略。 传入的customer对象确实包含列表CustomerTypes应该与有关:

[0] => { Id: 1, Type: "Finance", Customers: Null },
[1] => { Id: 2, Type: "Insurance", Customers: Null }
[2] => { Id: 3, Type: "Electronics", Customers: Null }

但是,而不是看这个列表和添加/删除相关的实体,EF只是忽略它。 新的关联被忽略,现有协会仍然即使它们应该被删除。

插入客户到数据库时,我也有类似的问题,当我调整这些实体的状态,这是固定EntityState.Unchanged 。 当然,我想在我的更新方案应用此相同的魔法修复:

public void Put([FromBody]CustomerModel customer)
{
    using (var context = new MyContext())
    {
        foreach (var customertype in customer.CustomerTypes)
        {
            context.Entry(customertype).State = EntityState.Unchanged;
        }

        context.Customers.Attach(customer);
        context.Entry(customer).State = EntityState.Modified;
        context.SaveChanges();
    }
}

但是EF持续显示相同的行为。

有想法该怎么解决这个吗? 或者我应该真的只是做一个手动清晰的列表CustomerTypes ,然后手动添加它们?

提前致谢。

J.P

Answer 1:

这不是仅通过设置实体状态确实可解。 你必须从数据库中首先包括其目前所有类型的加载客户,然后根据客户发布的更新类型的集合从删除类型,或添加类型来加载客户。 更改跟踪将做休息,以删除连接表或插入新条目的条目:

public void Put([FromBody]CustomerModel customer)
{
    using (var context = new MyContext())
    {
        var customerInDb = context.Customers.Include(c => c.CustomerTypes)
            .Single(c => c.Id == customer.Id);

        // Updates the Name property
        context.Entry(customerInDb).CurrentValues.SetValues(customer);

        // Remove types
        foreach (var typeInDb in customerInDb.CustomerTypes.ToList())
            if (!customer.CustomerTypes.Any(t => t.Id == typeInDb.Id))
                customerInDb.CustomerTypes.Remove(typeInDb);

        // Add new types
        foreach (var type in customer.CustomerTypes)
            if (!customerInDb.CustomerTypes.Any(t => t.Id == type.Id))
            {
                context.CustomerTypes.Attach(type);
                customerInDb.CustomerTypes.Add(type);
            }

        context.SaveChanges();
    }
}


Answer 2:

一个清洁的解决办法是:

public void Put([FromBody]CustomerModel customer)
{
    using (var context = new MyContext())
    {
        var customerInDb = context.Customers.Include(c => c.CustomerTypes)
            .Single(c => c.Id == customer.Id);

        // Updates the Name property
        context.Entry(customerInDb).CurrentValues.SetValues(customer);

        // Remove types
        customer.CustomerTypes.Clear();

        // Add new types
        foreach (var type in customer.CustomerTypes) 
        {
            context.CustomerTypes.Attach(type);
            customerInDb.CustomerTypes.Add(type);
        }

        context.SaveChanges();
    }
}


文章来源: EF5 code first with ASP.NET Web API: Update entity with many-to-many relationship