Entity framework 如何针对使用子列表的实体框架编写通用WebAPI Put方法?

Entity framework 如何针对使用子列表的实体框架编写通用WebAPI Put方法?,entity-framework,asp.net-web-api,Entity Framework,Asp.net Web Api,我正在修补WebAPI以创建实体框架的通用实现。我能够很好地实现大多数方法,但我发现在非平凡的情况下,PUT很棘手。最常见的在线实现适用于简单实体: [HttpPut] [ActionName("Endpoint")] public virtual T Put(T entity) { var db = GetDbContext(); var entry = db.Entry(entity); entry.State

我正在修补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;
    }
在MVC控制器中,您可以简单地使用“UpdateModel”,它将根据需要添加/更新/删除子项,但是该方法在ApicController上不可用。我知道从数据库中获取原始项需要一些代码,它需要使用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,使其能够处理子列表?

例程不验证实体,而是填充先前存在的实体

    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);            
    }
protected virtual void UpdateModel(T original,bool overrideForEmptyList=true)
{
var json=ControllerContext.Request.Content.ReadAsStringAsync().Result;
UpdateModel(json、原始、overrideForEmptyList);
}
私有void UpdateModel(字符串json,T original,bool overrideForEmptyList=true)
{
var newValues=JsonConvert.DeserializeObject(json);
foreach(原始.GetType().GetProperties()中的var属性)
{
var isEnumerable=property.PropertyType.GetInterfaces().Any(t=>t.IsGenericType&&t.GetGenericTypeDefinition()==typeof(IEnumerable));
如果(isEnumerable&&property.PropertyType!=typeof(字符串))
{
var propertyOriginalValue=property.GetValue(原始,空);
if(propertyOriginalValue!=null)
{
var propertyNewValue=property.GetValue(newValues,null);
if(propertyNewValue!=null&(overrideForEmptyList | | |((IEnumerable)propertyNewValue).Any())
{
property.SetValue(原始,空);
}
}
}
}
PopulateObject(json,原始);
}
公共空缺职位()
{           
var-sample=Pessoa.FindById(12);
更新模型(样本);
}
    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);            
    }