Asp.net mvc 是否可以仅自动更新现有实体对象上的选定属性而不接触其他属性

Asp.net mvc 是否可以仅自动更新现有实体对象上的选定属性而不接触其他属性,asp.net-mvc,asp.net-mvc-3,entity-framework,entity-framework-4,objectcontext,Asp.net Mvc,Asp.net Mvc 3,Entity Framework,Entity Framework 4,Objectcontext,假设我在实体类public bool isActive等中有一组布尔属性。这些值将通过在web应用程序中设置复选框来操作。我一次只回发一个已更改的名称/值对和主键,比如{isActive:true,NewsPageID:34},默认的模型绑定器将创建一个仅设置了这两个属性的NewsPage对象。现在,如果我运行下面的代码,它不仅会更新在模型绑定器创建的NewsPage对象上设置的属性值,而且当然还会尝试为现有实体对象的所有其他未设置的值设置为null,因为它们没有在模型绑定器创建的NewsPag

假设我在实体类
public bool isActive
等中有一组布尔属性。这些值将通过在web应用程序中设置复选框来操作。我一次只回发一个已更改的名称/值对和主键,比如
{isActive:true,NewsPageID:34}
,默认的模型绑定器将创建一个仅设置了这两个属性的NewsPage对象。现在,如果我运行下面的代码,它不仅会更新在模型绑定器创建的NewsPage对象上设置的属性值,而且当然还会尝试为现有实体对象的所有其他未设置的值设置为null,因为它们没有在模型绑定器创建的NewsPage对象上设置

是否可能以某种方式告诉EntityFramework不要查看设置为null的属性,并尝试将这些更改保留回检索到的实体对象和数据库?也许我可以编写一些代码,只使用model binder创建的NewsPage对象上的非null值及其属性名,并且只尝试更新这些特定属性

    [HttpPost]
    public PartialViewResult SaveNews(NewsPage Np)
    {
        Np.ModifyDate = DateTime.Now;
        _db.NewsPages.Attach(Np);
        _db.ObjectStateManager.ChangeObjectState(Np, System.Data.EntityState.Modified);
        _db.SaveChanges();
        _db.Dispose();


        return PartialView("MonthNewsData");
    }
我当然可以做下面的事情,但我觉得这不是最佳解决方案。特别是考虑到我需要设置6个布尔属性

[HttpPost]
public PartialViewResult SaveNews(int NewsPageID, bool isActive, bool isOnFrontPage)
{
        if (isActive != null)   { //Get entity and update this property }
        if (isOnFontPage != null) { //Get entity and update this property }
}

你可以有两种选择

  • 为该操作注册自定义模型绑定器。在自定义模型绑定器中,您必须从数据库中获取完整的对象,并且只更新发布的属性

  • 使用视图模型。而不是直接将
    新闻页
    模型作为操作参数。可以创建包含必要特性的自定义视图模型。在操作中,您必须调用db以获取完整的
    新闻页面
    实例,并仅更新视图模型中的相应属性


  • API不是强类型的,但您可以按如下方式执行
    DbContext
    API对此有更好的支持

    [HttpPost]
    public PartialViewResult SaveNews(NewsPage Np)
    {
        Np.ModifyDate = DateTime.Now;
        _db.NewsPages.Attach(Np);
        var entry = _db.ObjectStateManager.GetObjectStateEntry(Np);
    
        var cv = entry.CurrentValues;
    
        if (isActive)
        {
            cv.SetBoolean(cv.GetOrdinal("isActive"), true);
        }
    
        _db.SaveChanges();
        _db.Dispose();
    
        return PartialView("MonthNewsData");
    }
    

    有点难看,但在我的例子中,这样做不需要创建和注册自定义模型绑定器,也不需要使用多个if语句

        [HttpPost]
        public void SaveNews(string propname, bool propvalue, int PageID)
        {
            var prop = typeof(NewsPage).GetProperties().FirstOrDefault(x => x.Name.ToLower() == propname.ToLower());
            var Np = _db.NewsPages.FirstOrDefault(x => x.PageID == PageID);
            prop.SetValue(Np, propvalue, null);
    
             Np.ModifyDate = DateTime.Now;
            _db.SaveChanges();
            _db.Dispose();
    
        }
    

    将未更改的道具传递给模型绑定器可能会更容易,或者编写一个自定义道具并在那里获取完整的对象。模型绑定器解决方案听起来是可行的,考虑到它将只匹配集合,并且只针对模型发布名称/值对,在我的情况下,模型可能是数据库中的完整对象。然而,ViewModel方法在处理NewsPage对象时并没有任何优势。当然,我可以为name、value和pageid设置单独的属性,但这也可以从NewsPage对象中提取。