복붙노트

[SQL] 어떻게 엔티티 프레임 워크를 사용하여 하나 개의 필드를 업데이트하는?

SQL

어떻게 엔티티 프레임 워크를 사용하여 하나 개의 필드를 업데이트하는?

여기에 테이블입니다

사용자

UserId
UserName
Password
EmailAddress

및 코드 ..

public void ChangePassword(int userId, string password){
//code to update the password..
}

해결법

  1. ==============================

    1.라디의 대답은 DbContext을 (EF 4.1에서 소개) 사용하도록 업데이트 :

    라디의 대답은 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();
      }
    }
    
  2. ==============================

    2.당신은 속성이 방법으로 갱신 할 필요가있는 EF를 알 수 있습니다 :

    당신은 속성이 방법으로 갱신 할 필요가있는 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();
      }
    }
    
  3. ==============================

    3.당신은 기본적으로 두 가지 옵션이 있습니다 :

    당신은 기본적으로 두 가지 옵션이 있습니다 :

    이 경우, 구체적으로이 문제를 처리하는 방법 EF까지입니다. 난 그냥이 테스트 케이스에 난 단지, 어떤 EF가 생성하는 것은 너무 수동으로 만들 것입니다 무엇을 꽤 많이있는 객체의 단일 필드를 변경 - 같은 것을 :

    `UPDATE dbo.Users SET Password = @Password WHERE UserId = @UserId`
    

    EF 그래서 열이 실제로 변경 한 내용을 알아낼 수있는 스마트 충분하고, 실제로 필요한 바로 그 업데이트를 처리 할 수있는 T-SQL 문을 생성합니다.

  4. ==============================

    4.나는이를 사용하고 있습니다 :

    나는이를 사용하고 있습니다 :

    실재:

    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();
    
  5. ==============================

    5.모두 당신이 필요하므로 엔티티 프레임 워크 코어에서, 항목 수익률을 연결합니다 :

    모두 당신이 필요하므로 엔티티 프레임 워크 코어에서, 항목 수익률을 연결합니다 :

    var user = new User { Id = userId, Password = password };
    db.Users.Attach(user).Property(x => x.Password).IsModified = true;
    db.SaveChanges();
    
  6. ==============================

    6.이 문제에 대한 해결책을 찾고있는 동안, 나는 패트릭 Desjardins에 '블로그를 통해 GONeale의 대답에 변화를 발견 :

    이 문제에 대한 해결책을 찾고있는 동안, 나는 패트릭 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();
    }
    
    ...Update(Model, d=>d.Name);
    //or
    ...Update(Model, d=>d.Name, d=>d.SecondProperty, d=>d.AndSoOn);
    

    (A 다소 유사한 솔루션도 여기에 주어집니다 : https://stackoverflow.com/a/5749469/2115384)

    나는 현재 내 자신의 코드에서 사용하고있는 방법은,도 유형 ExpressionType.Convert의 LINQ () 표현식을 처리하기 위해 확장했다. 이 가이 드 및 기타 개체 속성을 가진 예를 들어, 내 경우에는 필요했다. 사람들은 변환 (에 '포장') 때문에 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();
    }
    
  7. ==============================

    7.내가 여기에 게임에 늦었어요,하지만 내가 그 일을하고 어떻게, 나는이 만족스러운 된 솔루션 동안 사냥을 보냈다; 당신이 명시 적으로 어쨌든 웹 양식 주입을 방지하기 위해 더 안전는 "화이트리스트"개념을 통해 무엇인지 정의로이 만 변경되는 필드에 대한 UPDATE 문을 생성합니다.

    내가 여기에 게임에 늦었어요,하지만 내가 그 일을하고 어떻게, 나는이 만족스러운 된 솔루션 동안 사냥을 보냈다; 당신이 명시 적으로 어쨌든 웹 양식 주입을 방지하기 위해 더 안전는 "화이트리스트"개념을 통해 무엇인지 정의로이 만 변경되는 필드에 대한 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를 통해 WAS)과 같이 호출 할 것입니다 :

    if (!session.Update(franchiseViewModel.Franchise, new[]
        {
          "Name",
          "StartDate"
      }))
      throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
    
  8. ==============================

    8.나는이 오래된 스레드 알고 있지만 나는 또한 비슷한 솔루션을 찾고있었습니다와 도쿠 이렇게 제공 @ 솔루션으로 이동하기로 결정했다. 내가 @Imran Rizvi가 자주 묻는 질문에 대한 답을 주석하고있어, 나는 쇼 그 비슷한 구현 도쿠 이렇게 링크 @ 따랐다. @Imran Rizvi의 질문은 '그것이 대리자 형식이 아니기 때문에'그가] [> 식 '유형에 람다 식을 변환 할 수 없습니다'를 제공하는 솔루션을 사용하여 오류가 발생 된 것이 었습니다. 난 경우 누군가 수정 프로그램이 오류가 다른이 게시물에 건너 와서 도쿠 - 그래서 솔루션 @ 사용하기로 결정하는 것이 도쿠-그래서 솔루션 @로 만든 작은 수정을 제공하고 싶었다.

    나는이 오래된 스레드 알고 있지만 나는 또한 비슷한 솔루션을 찾고있었습니다와 도쿠 이렇게 제공 @ 솔루션으로 이동하기로 결정했다. 내가 @Imran Rizvi가 자주 묻는 질문에 대한 답을 주석하고있어, 나는 쇼 그 비슷한 구현 도쿠 이렇게 링크 @ 따랐다. @Imran Rizvi의 질문은 '그것이 대리자 형식이 아니기 때문에'그가] [> 식 '유형에 람다 식을 변환 할 수 없습니다'를 제공하는 솔루션을 사용하여 오류가 발생 된 것이 었습니다. 난 경우 누군가 수정 프로그램이 오류가 다른이 게시물에 건너 와서 도쿠 - 그래서 솔루션 @ 사용하기로 결정하는 것이 도쿠-그래서 솔루션 @로 만든 작은 수정을 제공하고 싶었다.

    문제는, Update 메서드의 두 번째 인수입니다

    public int Update(T entity, Expression<Func<T, object>>[] properties). 
    

    제공되는 구문을 사용하여이 메서드를 호출 ...

    Update(Model, d=>d.Name, d=>d.SecondProperty, d=>d.AndSoOn); 
    

    당신은 너무로 두 번째 인수 앞에 'PARAMS'키워드를 추가해야합니다.

    public int Update(T entity, params Expression<Func<T, object>>[] properties)
    

    당신이, 당신이 '새로운'키워드를 추가해야 Update 메서드를 호출하는 다음 메서드 서명을 변경 배열의 크기를 지정한 다음 마지막으로 갱신 각 속성에 대한 구문 초기화 컬렉션 개체를 사용하지 않으려는 경우 또는 본 이하.

    Update(Model, new Expression<Func<T, object>>[3] { d=>d.Name }, { d=>d.SecondProperty }, { d=>d.AndSoOn });
    

    배열의 당신은 또한 배열의 크기를 지정해야합니다 때문에, 배열에 업데이트 할 수있는 속성을 통과해야하므로 도쿠-그래서 예 @에서 그는 표현의 배열을 지정하는 것입니다. 이를 방지하기 위해 당신은 또한 대신 배열을 IEnumerable을 사용하는 식 인수를 변경할 수 있습니다.

    여기 @ 도쿠-그래서 솔루션의 내 구현입니다.

    public int Update<TEntity>(LcmsEntities dataContext, DbEntityEntry<TEntity> entityEntry, params Expression<Func<TEntity, object>>[] properties)
         where TEntity: class
        {
            entityEntry.State = System.Data.Entity.EntityState.Unchanged;
    
            properties.ToList()
                .ForEach((property) =>
                {
                    var propertyName = string.Empty;
                    var 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);
                    }
    
                    entityEntry.Property(propertyName).IsModified = true;
                });
    
            dataContext.Configuration.ValidateOnSaveEnabled = false;
    
            return dataContext.SaveChanges();
        }
    

    용법:

    this.Update<Contact>(context, context.Entry(modifiedContact), c => c.Active, c => c.ContactTypeId);
    

    도쿠 이렇게 일반의를 사용하여 멋진 접근 방식을 제공 @, 나는 내 문제를 해결하기 위해 개념을 사용하지만, 그냥 그대로 도쿠 - 그래서 솔루션 @ 사용이 게시물 아무도 사용 오류 질문에 대한 답변하지 연결된 후 모두 수 없습니다.

  9. ==============================

    9.엔티티 프레임 워크는 DbContext를 통해 데이터베이스에서 쿼리 것을 개체에 대한 변경 사항을 추적합니다. 예를 들어, DbContext 인스턴스 이름은 dbContext 경우

    엔티티 프레임 워크는 DbContext를 통해 데이터베이스에서 쿼리 것을 개체에 대한 변경 사항을 추적합니다. 예를 들어, DbContext 인스턴스 이름은 dbContext 경우

    public void ChangePassword(int userId, string password){
         var user = dbContext.Users.FirstOrDefault(u=>u.UserId == userId);
         user.password = password;
         dbContext.SaveChanges();
    }
    
  10. ==============================

    10.EntityFramework 코어 2.X에서 첨부 할 필요가 없다 :

    EntityFramework 코어 2.X에서 첨부 할 필요가 없다 :

     // get a tracked entity
     var entity = context.User.Find(userId);
     entity.someProp = someValue;
     // other property changes might come here
     context.SaveChanges();
    

    SQL 서버에서 이것을 시도하고 프로파일 :

    exec sp_executesql N'SET NOCOUNT ON;
    UPDATE [User] SET [someProp] = @p0
    WHERE [UserId] = @p1;
    SELECT @@ROWCOUNT;
    
    ',N'@p1 int,@p0 bit',@p1=1223424,@p0=1
    

    이미로드 실체는 SELECT 트리거하지 않도록합니다을 찾아 자동으로 (워드 프로세서에서) 필요한 경우 개체를 첨부합니다

        ///     Finds an entity with the given primary key values. If an entity with the given primary key values
        ///     is being tracked by the context, then it is returned immediately without making a request to the
        ///     database. Otherwise, a query is made to the database for an entity with the given primary key values
        ///     and this entity, if found, is attached to the context and returned. If no entity is found, then
        ///     null is returned.
    
  11. ==============================

    11.나는 ValueInjecter는 다음 사용하여 데이터베이스 엔티티로 모델을 바인딩 주입 nuget 사용

    나는 ValueInjecter는 다음 사용하여 데이터베이스 엔티티로 모델을 바인딩 주입 nuget 사용

    public async Task<IHttpActionResult> Add(CustomBindingModel model)
    {
       var entity= await db.MyEntities.FindAsync(model.Id);
       if (entity== null) return NotFound();
    
       entity.InjectFrom<NoNullsInjection>(model);
    
       await db.SaveChangesAsync();
       return Ok();
    }
    

    등록 서버가있는 거 경우는 null를 업데이트하지 않습니다 사용자 정의 규칙의 사용을 주목하라.

    public class NoNullsInjection : LoopInjection
    {
        protected override void SetValue(object source, object target, PropertyInfo sp, PropertyInfo tp)
        {
            if (sp.GetValue(source) == null) return;
            base.SetValue(source, target, sp, tp);
        }
    }
    

    용법:

    target.InjectFrom<NoNullsInjection>(source);
    

    이 답변을 조회

    당신은 속성이 의도적으로 null로 클리어 여부를 알 수 없습니다 또는 그냥 값을 가지고 있지 않았다. 즉, 속성 값은 다른 값으로 대체하지만, 삭제 할 수는 없습니다.

  12. ==============================

    12.나는 다음을 제안 몇 가지 제안을 결합 :

    나는 다음을 제안 몇 가지 제안을 결합 :

        async Task<bool> UpdateDbEntryAsync<T>(T entity, params Expression<Func<T, object>>[] properties) where T : class
        {
            try
            {
                var entry = db.Entry(entity);
                db.Set<T>().Attach(entity);
                foreach (var property in properties)
                    entry.Property(property).IsModified = true;
                await db.SaveChangesAsync();
                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("UpdateDbEntryAsync exception: " + ex.Message);
                return false;
            } 
        }
    

    호출

    UpdateDbEntryAsync(dbc, d => d.Property1);//, d => d.Property2, d => d.Property3, etc. etc.);
    

    OR로

    await UpdateDbEntryAsync(dbc, d => d.Property1);
    

    OR로

    bool b = UpdateDbEntryAsync(dbc, d => d.Property1).Result;
    
  13. ==============================

    13.나는 동일을 찾고 있었다 그리고 마지막으로 나는 해결책을 발견

    나는 동일을 찾고 있었다 그리고 마지막으로 나는 해결책을 발견

    using (CString conn = new CString())
    {
        USER user = conn.USERs.Find(CMN.CurrentUser.ID);
        user.PASSWORD = txtPass.Text;
        conn.SaveChanges();
    }
    

    이 마법처럼 나를 위해 작동 날 믿어.

  14. ==============================

    14.이것은 (OBJ의 최종 도착, OBJ SRC)는 완전히 유연하게 사용자 정의 InjectNonNull를 사용하여, 내가 사용하는 것입니다

    이것은 (OBJ의 최종 도착, OBJ SRC)는 완전히 유연하게 사용자 정의 InjectNonNull를 사용하여, 내가 사용하는 것입니다

    [HttpPost]
    public async Task<IActionResult> Post( [FromQuery]Models.Currency currency ) {
      if ( ModelState.IsValid ) {
        // find existing object by Key
        Models.Currency currencyDest = context.Currencies.Find( currency.Id ); 
    
        context.Currencies.Attach( currencyDest );
    
        // update only not null fields
        InjectNonNull( currencyDest, currency );
    
        // save
        await context.SaveChangesAsync( );
      }  
      return Ok();
    }
    
    // Custom method
    public static T InjectNonNull<T>( T dest, T src ) {
      foreach ( var propertyPair in PropertyLister<T, T>.PropertyMap ) {
        var fromValue = propertyPair.Item2.GetValue( src, null );
        if ( fromValue != null && propertyPair.Item1.CanWrite ) {
           propertyPair.Item1.SetValue( dest, fromValue, null );
        }
      }
      return dest;
    }
    
  15. ==============================

    15.

    public async Task<bool> UpdateDbEntryAsync(TEntity entity, params Expression<Func<TEntity, object>>[] properties)
    {
        try
        {
            this.Context.Set<TEntity>().Attach(entity);
            EntityEntry<TEntity> entry = this.Context.Entry(entity);
            entry.State = EntityState.Modified;
            foreach (var property in properties)
                entry.Property(property).IsModified = true;
            await this.Context.SaveChangesAsync();
            return true;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    
  16. ==============================

    16.

    public void ChangePassword(int userId, string password)
    {
      var user = new User{ Id = userId, Password = password };
      using (var db = new DbContextName())
      {
        db.Entry(user).State = EntityState.Added;
        db.SaveChanges();
      }
    }
    
  17. from https://stackoverflow.com/questions/3642371/how-to-update-only-one-field-using-entity-framework by cc-by-sa and MIT license