여기 테이블이 있습니다
사용자
UserId
UserName
Password
EmailAddress
그리고 코드 ..
public void ChangePassword(int userId, string password){
//code to update the password..
}
답변
Ladislav의 답변은 DbContext를 사용하도록 업데이트되었습니다 (EF 4.1에서 도입).
public void ChangePassword(int userId, string password)
{
var user = new User() { Id = userId, Password = password };
using (var db = new MyEfContextName())
{
db.Users.Attach(user);
db.Entry(user).Property(x => x.Password).IsModified = true;
db.SaveChanges();
}
}
답변
다음과 같은 방법으로 EF에 어떤 속성을 업데이트해야하는지 알 수 있습니다.
public void ChangePassword(int userId, string password)
{
var user = new User { Id = userId, Password = password };
using (var context = new ObjectContext(ConnectionString))
{
var users = context.CreateObjectSet<User>();
users.Attach(user);
context.ObjectStateManager.GetObjectStateEntry(user)
.SetModifiedProperty("Password");
context.SaveChanges();
}
}
답변
기본적으로 두 가지 옵션이 있습니다.
- 끝까지 EF로 가십시오.
userId
제공된 것을 기준으로 객체를로드-전체 객체가로드됩니다.password
필드를 업데이트- 컨텍스트
.SaveChanges()
메소드를 사용하여 오브젝트를 다시 저장하십시오.
이 경우이를 자세히 처리하는 방법은 EF에 달려 있습니다. 방금 이것을 테스트했으며 객체의 단일 필드 만 변경하는 경우 EF가 만드는 것은 수동으로 만드는 것입니다.
`UPDATE dbo.Users SET Password = @Password WHERE UserId = @UserId`
따라서 EF는 실제로 변경된 열을 파악할 수있을 정도로 똑똑하며 실제로 필요한 업데이트 만 처리하기 위해 T-SQL 문을 만듭니다.
- T-SQL 코드에서 필요한 것을 정확하게 수행하는 저장 프로 시저를 정의하고 (
Password
주어진 열을 업데이트하고UserId
다른 것은 기본적으로 실행하지 않음UPDATE dbo.Users SET Password = @Password WHERE UserId = @UserId
) EF 모델에서 해당 저장 프로 시저에 대한 함수 가져 오기를 작성하고 이것을 호출합니다. 위에서 설명한 단계를 수행하는 대신 기능
답변
Entity Framework Core Attach
에서 항목을 반환하므로 필요한 것은 다음과 같습니다.
var user = new User { Id = userId, Password = password };
db.Users.Attach(user).Property(x => x.Password).IsModified = true;
db.SaveChanges();
답변
나는 이것을 사용하고있다 :
실재:
public class Thing
{
[Key]
public int Id { get; set; }
public string Info { get; set; }
public string OtherStuff { get; set; }
}
dbcontext :
public class MyDataContext : DbContext
{
public DbSet<Thing > Things { get; set; }
}
접근 자 코드 :
MyDataContext ctx = new MyDataContext();
// FIRST create a blank object
Thing thing = ctx.Things.Create();
// SECOND set the ID
thing.Id = id;
// THIRD attach the thing (id is not marked as modified)
db.Things.Attach(thing);
// FOURTH set the fields you want updated.
thing.OtherStuff = "only want this field updated.";
// FIFTH save that thing
db.SaveChanges();
답변
이 문제에 대한 해결책을 찾는 동안 Patrick Desjardins의 블로그를 통해 GONeale의 답변에서 변형이 발견되었습니다 .
public int Update(T entity, Expression<Func<T, object>>[] properties)
{
DatabaseContext.Entry(entity).State = EntityState.Unchanged;
foreach (var property in properties)
{
var propertyName = ExpressionHelper.GetExpressionText(property);
DatabaseContext.Entry(entity).Property(propertyName).IsModified = true;
}
return DatabaseContext.SaveChangesWithoutValidation();
}
” 보시다시피, 두 번째 매개 변수로 함수의 표현식을 취합니다. 그러면 업데이트 할 특성을 Lambda 표현식에 지정하여이 메소드를 사용할 수 있습니다. “
...Update(Model, d=>d.Name);
//or
...Update(Model, d=>d.Name, d=>d.SecondProperty, d=>d.AndSoOn);
( https://stackoverflow.com/a/5749469/2115384 ) 다소 비슷한 솔루션이 제공됩니다.
현재 내 코드에서 사용하고있는 메소드 는 (Linq) 유형의 표현식도 처리하도록 확장되었습니다 ExpressionType.Convert
. 이것은 필자의 경우 Guid
와 다른 객체 속성 과 함께 필요했습니다 . 그것들은 Convert ()에 ‘포장’되어 처리되지 않았습니다 System.Web.Mvc.ExpressionHelper.GetExpressionText
.
public int Update(T entity, Expression<Func<T, object>>[] properties)
{
DbEntityEntry<T> entry = dataContext.Entry(entity);
entry.State = EntityState.Unchanged;
foreach (var property in properties)
{
string propertyName = "";
Expression bodyExpression = property.Body;
if (bodyExpression.NodeType == ExpressionType.Convert && bodyExpression is UnaryExpression)
{
Expression operand = ((UnaryExpression)property.Body).Operand;
propertyName = ((MemberExpression)operand).Member.Name;
}
else
{
propertyName = System.Web.Mvc.ExpressionHelper.GetExpressionText(property);
}
entry.Property(propertyName).IsModified = true;
}
dataContext.Configuration.ValidateOnSaveEnabled = false;
return dataContext.SaveChanges();
}
답변
나는 여기서 게임에 늦었지만, 이것이 내가하는 일이다. 이렇게하면 UPDATE
웹 양식 삽입을 방지하기 위해보다 안전한 “화이트리스트”개념을 통해 필드를 명시 적으로 정의하므로 변경된 필드에 대해서만 명령문 이 생성 됩니다.
내 ISession 데이터 저장소에서 발췌 한 내용 :
public bool Update<T>(T item, params string[] changedPropertyNames) where T
: class, new()
{
_context.Set<T>().Attach(item);
foreach (var propertyName in changedPropertyNames)
{
// If we can't find the property, this line wil throw an exception,
//which is good as we want to know about it
_context.Entry(item).Property(propertyName).IsModified = true;
}
return true;
}
원하는 경우 try..catch로 묶을 수 있지만이 시나리오의 예외에 대해 발신자가 개인적으로 알고 싶습니다.
다음과 같은 방식으로 호출됩니다 (나에게 이것은 ASP.NET 웹 API를 통해 이루어졌습니다).
if (!session.Update(franchiseViewModel.Franchise, new[]
{
"Name",
"StartDate"
}))
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
