web-dev-qa-db-fra.com

Propriété d'exclusion lors de la mise à jour dans Entity Framework

Je cherchais un moyen approprié de marquer qu'une propriété ne devait PAS être modifiée lors de la mise à jour d'un modèle dans MVC.

Par exemple, prenons ce petit modèle:

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

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

alors la méthode d'édition créée par MVC ressemble à ceci:

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

maintenant, si ma vue ne contient pas le jeton, il sera annulé lors de cette modification.

Je cherche quelque chose comme ça: 

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

Le meilleur moyen que j’ai trouvé jusqu’à présent est d’être inclusif et de définir manuellement toutes les propriétés que je veux inclure, mais je ne souhaite vraiment que celles qui seront exclues.

59
Manuel Schweigert

on peut utiliser comme ça

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

il sera mis à jour mais sans propriété Token

112
Nitin Dominic

Créez un nouveau modèle avec un ensemble limité de propriétés que vous souhaitez mettre à jour.

C'est à dire. si votre modèle d'entité est:

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

Vous pouvez créer un modèle de vue personnalisé qui permettra à l'utilisateur de changer le nom, mais pas l'indicateur activé:

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

Lorsque vous souhaitez effectuer la mise à jour de la base de données, procédez comme suit:

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();
    }
}

Lorsque vous appelez cette méthode, vous mettez à jour le nom, mais la propriété Enabled reste inchangée. J'ai utilisé des modèles simples, mais je pense que vous comprendrez comment l'utiliser.

6
Admir Tuzović

J'imagine que vous ne souhaitez pas que la propriété soit modifiée dans certains cas, car si vous ne l'utilisez jamais dans votre application, supprimez-la simplement de votre modèle.

Si vous souhaitez l'utiliser uniquement dans certains scénarios et éviter son "annulation" dans le cas ci-dessus, vous pouvez essayer de:

  • Masquer le paramètre dans la vue avec HiddenFor:

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

Cela rendra votre valeur d'origine non modifiée et retransmise au contrôleur.

Chargez à nouveau votre objet dans le contrôleur à partir de votre DBSet et exécutez cette méthode. Vous pouvez spécifier à la fois une liste blanche et une liste noire de paramètres qui doivent ou non être mis à jour.

1
Jaime

J'ai créé un moyen simple de modifier les propriétés des entités que je partagerai avec vous . Ce code modifiera les propriétés Nom et Famille de l'entité:

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

Et ce code ignorera d’éditer les propriétés Name et Family de l’entité et éditera d’autres propriétés:

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

Utilisez cette 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
}
0
Ali Yousefie