Ответ 1
мы можем использовать это как
db.Entry(model).State = EntityState.Modified;
db.Entry(model).Property(x => x.Token).IsModified = false;
db.SaveChanges();
он обновится, но без свойства Token
Я искал подходящий способ отметить свойство, которое НЕ будет изменено при обновлении модели в MVC.
Например, возьмем эту маленькую модель:
class Model
{
[Key]
public Guid Id {get; set;}
public Guid Token {get; set;}
//... lots of properties here ...
}
то способ редактирования MVC выглядит следующим образом:
[HttpPost]
public ActionResult Edit(Model model)
{
if (ModelState.IsValid)
{
db.Entry(model).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
теперь, если мой вид не содержит токена, он будет аннулирован через это редактирование.
Я ищу что-то вроде этого:
db.Entry(model).State = EntityState.Modified;
db.Entry(model).Property(x => x.Token).State = PropertyState.Unmodified;
db.SaveChanges();
Самый лучший способ, который я нашел, - быть включенным и задавать все свойства, которые я хочу включить вручную, но я действительно хочу только сказать, какие из них следует исключить.
мы можем использовать это как
db.Entry(model).State = EntityState.Modified;
db.Entry(model).Property(x => x.Token).IsModified = false;
db.SaveChanges();
он обновится, но без свойства Token
Создайте новую модель, которая будет иметь ограниченный набор свойств, которые вы хотите обновить.
т.е. если ваша модель объекта:
public class User
{
public int Id {get;set;}
public string Name {get;set;}
public bool Enabled {get;set;}
}
Вы можете создать пользовательскую модель представления, которая позволит пользователю изменять имя, но не флаг Enabled:
public class UserProfileModel
{
public int Id {get;set;}
public string Name {get;set;}
}
Если вы хотите обновить базу данных, выполните следующие действия:
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();
}
}
При вызове этого метода вы обновите имя, но свойство Enabled останется без изменений. Я использовал простые модели, но я думаю, вы получите изображение, как его использовать.
Любой, кто ищет, как добиться этого на EF Core. Это в основном то же самое, но ваш IsModified должен быть после добавления модели для обновления.
db.Update(model);
db.Entry(model).Property(x => x.Token).IsModified = false;
db.SaveChanges();
Я сделал простой способ редактировать свойства сущностей, которыми я поделюсь с вами. этот код будет редактировать свойства имени и семейства объекта:
public void EditProfileInfo(ProfileInfo profileInfo)
{
using (var context = new TestContext())
{
context.EditEntity(profileInfo, TypeOfEditEntityProperty.Take, nameof(profileInfo.Name), nameof(profileInfo.Family));
}
}
И этот код будет игнорировать для редактирования свойств имени и семейства объекта, а также для редактирования других свойств:
public void EditProfileInfo(ProfileInfo profileInfo)
{
using (var context = new TestContext())
{
context.EditEntity(profileInfo, TypeOfEditEntityProperty.Ignore, nameof(profileInfo.Name), nameof(profileInfo.Family));
}
}
Используйте это расширение:
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
}
Я думаю, вы не хотите, чтобы свойство было изменено только в некоторых случаях, потому что, если вы не собираетесь использовать его никогда в своем приложении, просто удалите его из своей модели.
Если вы хотите использовать его только в некоторых сценариях и избегать его "аннулирования" в приведенном выше случае, вы можете попробовать:
Скрыть параметр в представлении с помощью HiddenFor:
@Html.HiddenFor(m => m.Token)
Это приведет к тому, что ваше исходное значение будет сохранено без изменений и передано обратно контроллеру.
TryUpdateModel
: http://msdn.microsoft.com/en-us/library/dd460189(v=vs.108).aspxЗагрузите снова свой объект в контроллере из своего DBSet
и запустите этот метод. Вы можете указать как белый список, так и черный список параметров, которые должны или не должны обновляться.