C# 在实体框架中排除更新时的属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12661881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:02:38  来源:igfitidea点击:

Exclude Property on Update in Entity Framework

c#asp.net-mvcentity-framework

提问by Manuel Schweigert

I've been looking for a proper way to mark a property to NOT be changed when updating a model in MVC.

我一直在寻找一种正确的方法来标记在 MVC 中更新模型时不会更改的属性。

For example, let's take this small model:

例如,让我们以这个小模型为例:

class Model
{
    [Key]
    public Guid Id {get; set;}
    public Guid Token {get; set;}

    //... lots of properties here ...
}

then the edit method MVC creates looks like this:

那么 MVC 创建的编辑方法如下所示:

[HttpPost]
public ActionResult Edit(Model model)
{
    if (ModelState.IsValid)
    {
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(model);
}

now if my View does not contain the Token, it will be nullified through that edit.

现在,如果我的视图不包含令牌,它将通过该编辑无效。

I'm looking for something like this:

我正在寻找这样的东西:

db.Entry(model).State = EntityState.Modified;
db.Entry(model).Property(x => x.Token).State = PropertyState.Unmodified;
db.SaveChanges();

The best way so far I found is to be inclusive and set all properties I want included by hand, but I really only want to say which ones to be excluded.

到目前为止,我发现的最好方法是包容并手动设置我想要包含的所有属性,但我真的只想说要排除哪些属性。

采纳答案by Nitin Dominic

we can use like this

我们可以这样使用

 db.Entry(model).State = EntityState.Modified;
 db.Entry(model).Property(x => x.Token).IsModified = false;
 db.SaveChanges();

it will update but without Token property

它会更新但没有 Token 属性

回答by Admir Tuzovi?

Create new model that will have limited set of properties that you want to update.

创建将具有要更新的有限属性集的新模型。

I.e. if your entity model is:

即,如果您的实体模型是:

public class User
{
    public int Id {get;set;}
    public string Name {get;set;}
    public bool Enabled {get;set;}
}

You can create custom view model that will allow user to change Name, but not Enabled flag:

您可以创建自定义视图模型,允许用户更改名称,但不能更改启用标志:

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

When you want to do database update, you do the following:

当您想要进行数据库更新时,您可以执行以下操作:

YourUpdateMethod(UserProfileModel model)
{
    using(YourContext ctx = new YourContext())
    { 
        User user = new User { Id = model.Id } ;   /// stub model, only has Id
        ctx.Users.Attach(user); /// track your stub model
        ctx.Entry(user).CurrentValues.SetValues(model); /// reflection
        ctx.SaveChanges();
    }
}

When you call this method, you will update the Name, but Enabled property will remain unchanged. I used simple models, but I think you'll get the picture how to use it.

当您调用此方法时,您将更新 Name,但 Enabled 属性将保持不变。我使用了简单的模型,但我想你会知道如何使用它。

回答by Jaime

I guess you don't want the property to be changed just in some cases, because if you are not going to use it never in your application, just remove it from your model.

我猜您不希望在某些情况下更改属性,因为如果您永远不会在应用程序中使用它,只需将其从模型中删除。

In case you want to use it just in some scenarios and avoid its "nullification" in the case above, you can try to:

如果您只想在某些情况下使用它并避免在上述情况下“无效”,您可以尝试:

  • Hide the parameter in the view with HiddenFor:

    @Html.HiddenFor(m => m.Token)

  • 使用 HiddenFor 在视图中隐藏参数:

    @Html.HiddenFor(m => m.Token)

This will make your original value to be kept unmodified and passed back to the controller.

这将使您的原始值保持不变并传递回控制器。

Load again your object in the controller from your DBSetand run this method. You can specify both a white list and a blacklist of parameters that shall or shall not be update.

从您的控制器中再次加载您的对象DBSet并运行此方法。您可以指定应该或不应该更新的参数的白名单和黑名单。

回答by Ali Yousefi

I made an easy way to edit properties of entities I will share with you. this code will edit Name and Family properties of entity:

我做了一个简单的方法来编辑我将与你分享的实体的属性。此代码将编辑实体的 Name 和 Family 属性:

    public void EditProfileInfo(ProfileInfo profileInfo)
    {
        using (var context = new TestContext())
        {
            context.EditEntity(profileInfo, TypeOfEditEntityProperty.Take, nameof(profileInfo.Name), nameof(profileInfo.Family));
        }
    }

And this code will ignore to edit Name and Family properties of entity and it will edit another properties:

此代码将忽略编辑实体的 Name 和 Family 属性,并将编辑另一个属性:

    public void EditProfileInfo(ProfileInfo profileInfo)
    {
        using (var context = new TestContext())
        {
            context.EditEntity(profileInfo, TypeOfEditEntityProperty.Ignore, nameof(profileInfo.Name), nameof(profileInfo.Family));
        }
    }

Use this extension:

使用这个扩展:

public static void EditEntity<TEntity>(this DbContext context, TEntity entity, TypeOfEditEntityProperty typeOfEditEntityProperty, params string[] properties)
   where TEntity : class
{
    var find = context.Set<TEntity>().Find(entity.GetType().GetProperty("Id").GetValue(entity, null));
    if (find == null)
        throw new Exception("id not found in database");
    if (typeOfEditEntityProperty == TypeOfEditEntityProperty.Ignore)
    {
        foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty))
        {
            if (!item.CanRead || !item.CanWrite)
                continue;
            if (properties.Contains(item.Name))
                continue;
            item.SetValue(find, item.GetValue(entity, null), null);
        }
    }
    else if (typeOfEditEntityProperty == TypeOfEditEntityProperty.Take)
    {
        foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty))
        {
            if (!item.CanRead || !item.CanWrite)
                continue;
            if (!properties.Contains(item.Name))
                continue;
            item.SetValue(find, item.GetValue(entity, null), null);
        }
    }
    else
    {
        foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty))
        {
            if (!item.CanRead || !item.CanWrite)
                continue;
            item.SetValue(find, item.GetValue(entity, null), null);
        }
    }
    context.SaveChanges();
}

public enum TypeOfEditEntityProperty
{
    Ignore,
    Take
}

回答by Jesse

Anyone looking for how to achieve this on EF Core. It's basically the same but your IsModified needs to be after you add the model to be updated.

任何人都在寻找如何在 EF Core 上实现这一目标。它基本上是一样的,但你的 IsModified 需要在你添加要更新的模型之后。

db.Update(model);
db.Entry(model).Property(x => x.Token).IsModified = false;
db.SaveChanges();