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;}
}
사용자가 이름을 변경할 수 있지만 사용 플래그가 아닌 사용자 정의보기 모델을 만들 수 있습니다.
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();
}
}
이 메서드를 호출하면 Name이 업데이트되지만 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
하고이 메서드를 실행합니다. 업데이트하거나 업데이트하지 않을 매개 변수의 화이트리스트와 블랙리스트를 모두 지정할 수 있습니다.