3

我正在修补 WebAPI 以创建实体框架的通用实现。我能够很好地实现大多数方法,但我发现 PUT 在非平凡的情况下很棘手。最常见的在线实现适用于简单实体:

    [HttpPut]
    [ActionName("Endpoint")]
    public virtual T Put(T entity)
    {
        var db = GetDbContext();
        var entry = db.Entry(entity);
        entry.State = EntityState.Modified;
        var set = db.Set<T>();            
        set.Attach(entity);                     
        db.SaveChanges();
        return entity;
    }

...但不删除或更新子列表:

    public class Invoice
    {
         ...
         public virtual InvoiceLineItem {get; set;} //Attach method doesn't address these
    }

在 MVC 控制器中,您可以简单地使用“UpdateModel”,它会根据需要添加/更新/删除子级,但是该方法在 ApiController 上不可用。我知道从数据库中获取原始项目需要一些代码,并且需要使用 Include 来获取子列表,但不能完全找出复制 UpdateModel 功能的最佳方法:

    [HttpPut]
    [ActionName("Endpoint")]
    public virtual T Put(T entity)
    {
        var db = GetDbContext();
        var original = GetOriginalFor(entity); 
        //TODO: Something similar to UpdateModel(original), such as UpdateModel(original, entity);                  
        db.SaveChanges();
        return original;
    }

如何实现 UpdateModel 或以某种方式实现 Put 以处理子列表?

4

1 回答 1

1

该例程不验证实体,但填充预先存在的实体。

    protected virtual void UpdateModel<T>(T original, bool overrideForEmptyList = true)
    {
        var json = ControllerContext.Request.Content.ReadAsStringAsync().Result;
        UpdateModel<T>(json, original, overrideForEmptyList);
    }

    private void UpdateModel<T>(string json, T original, bool overrideForEmptyList = true)
    {
        var newValues = JsonConvert.DeserializeObject<Pessoa>(json);            
        foreach (var property in original.GetType().GetProperties())
        {
            var isEnumerable = property.PropertyType.GetInterfaces().Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>));

            if (isEnumerable && property.PropertyType != typeof(string))
            {
                var propertyOriginalValue = property.GetValue(original, null);
                if (propertyOriginalValue != null)
                {
                    var propertyNewValue = property.GetValue(newValues, null);

                    if (propertyNewValue != null && (overrideForEmptyList || ((IEnumerable<object>)propertyNewValue).Any()))
                    {
                        property.SetValue(original, null);
                    }
                }
            }
        }

        JsonConvert.PopulateObject(json, original);
    }

    public void Post()
    {           
        var sample = Pessoa.FindById(12);
        UpdateModel(sample);            
    }
于 2015-09-29T21:26:38.043 回答