代码之家  ›  专栏  ›  技术社区  ›  Pranay Rana

使用LINQ to SQL进行更新的最有效方法

  •  22
  • Pranay Rana  · 技术社区  · 15 年前

    我可以按照下面的函数更新我的员工记录吗?还是必须先查询员工集合,然后更新数据?

      public int updateEmployee(App3_EMPLOYEE employee)
      {
          DBContextDataContext db = new DBContextDataContext();
          db.App3_EMPLOYEEs.Attach(employee);
          db.SubmitChanges();
          return employee.PKEY;
      }
    

    或者我必须做以下工作?

    public int updateEmployee(App3_EMPLOYEE employee)
    {
        DBContextDataContext db = new DBContextDataContext();
        App3_EMPLOYEE emp = db.App3_EMPLOYEEs.Single(e => e.PKEY == employee.PKEY);
        db.App3_EMPLOYEEs.Attach(employee,emp);
        db.SubmitChanges();
        return employee.PKEY;
    }
    

    但我不想使用第二个选项。有什么有效的方法更新数据吗?

    我通过使用以下两种方法获得此错误:

    试图附加或添加一个不是新的实体,可能是从另一个DataContext加载的。不支持此操作。

    6 回复  |  直到 8 年前
        1
  •  9
  •   Maksim    12 年前

    我找到了以下解决这个问题的方法:

    1)获取和更新实体(我将使用这种方式,因为这对我来说没问题)

    public int updateEmployee(App3_EMPLOYEE employee)
    {
        AppEmployeeDataContext db = new AppEmployeeDataContext();
        App3_EMPLOYEE emp = db.App3_EMPLOYEEs.Single(e => e.PKEY == employee.PKEY);
        emp.FIRSTNAME = employee.FIRSTNAME;//copy property one by one 
        db.SubmitChanges();
        return employee.PKEY;
    }
    

    2)禁用ObjectTrackingEnabled,如下所示

    // but in this case lazy loading is not supported
    
    
        public AppEmployeeDataContext() : 
                        base(global::LinqLibrary.Properties.Settings.Default.AppConnect3DBConnectionString, mappingSource)
                {
                    this.ObjectTrackingEnabled = false;
                    OnCreated();
                }
    

    3)分离所有相关对象

    partial class App3_EMPLOYEE
    {
        public void Detach()
        {
            this._APP3_EMPLOYEE_EXTs = default(EntityRef<APP3_EMPLOYEE_EXT>);
        }
    }
    
     public int updateEmployee(App3_EMPLOYEE employee)
    {
        AppEmployeeDataContext db = new AppEmployeeDataContext();
        employee.Detach();
        db.App3_EMPLOYEEs.Attach(employee,true);
        db.SubmitChanges();
        return employee.PKEY;
    }
    

    4)在列中使用时间戳

     http://www.west-wind.com/weblog/posts/135659.aspx
    

    5)创建用于更新数据的存储过程并通过DB上下文调用它

        2
  •  3
  •   Pranay Rana    15 年前

    当没有rowversion列时,不能将修改后的实体附加到DataContext。相反,只要维护数据更改的副本,就可以在应用程序中存储原始实体。然后,当需要保存更改时,可以将原始实体附加到DataContext,更改其值以匹配修改后的实体值并提交更改。

    下面是一个例子:

    public int updateEmployee(App3_EMPLOYEE employee, App3_EMPLOYEE originalEmployee)
    {
        DBContextDataContext db = new DBContextDataContext();
        db.App3_EMPLOYEEs.Attach(originalEmployee);
    
        // TODO: Copy values from employee to original employee
    
        db.SubmitChanges();
        return employee.PKEY;
    }
    

    更新:

    数据库中有一个表,列ID、名称、注释

    // fetch an employee which will not be changed in the application
    Employee original;
    using(var db = new TestDbDataContext())
    {
      original = db.Employees.First(e => e.ID == 2);
    }
    
    // create an instance to work with
    var modified = new Employee {ID = original.ID, Name = original.Name, Notes = original.Notes};
    
    // change some info
    modified.Notes = string.Format("new notes as of {0}", DateTime.Now.ToShortTimeString());  
    // update
    using(var db = new TestDbDataContext())
    {
      db.Employees.Attach(original);
      original.Notes = modified.Notes;
      db.SubmitChanges();
    }
    
        3
  •  2
  •   Pranay Rana    13 年前

    关于这个话题有个讨论 here at MSDN s 建议使用ISVersion字段和Attach方法

        4
  •  2
  •   yoel halb    13 年前

    通过使用此重载,可以附加未附加的修改实体:

    db.App3_EMPLOYEEs.Attach(employee, true);//Attach as modfieied
    

    请注意,要使其工作,您需要在表中输入“timestamp”类型的“version”列。

        5
  •  1
  •   Adam Bilinski    11 年前

    这是我的知识库类中用于更新实体的函数

    protected void Attach(TEntity entity)
    {
       try
        {
           _dataContext.GetTable<TEntity>().Attach(entity);
           _dataContext.Refresh(RefreshMode.KeepCurrentValues, entity);
        }
        catch (DuplicateKeyException ex) //Data context knows about this entity so just update values
        {
           _dataContext.Refresh(RefreshMode.KeepCurrentValues, entity);
        }
    }
    

    Tentity是您的DB类,根据您的设置,您可能只想这样做。

    _dataContext.Attach(entity);
    
        6
  •  0
  •   ViRuSTriNiTy    8 年前

    使用此扩展方法更新列属性的所有属性:

    public static void SaveToOriginal<T>(this T original, T actual)
        {
            foreach (var prop in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(info => info.GetCustomAttribute<System.Data.Linq.Mapping.ColumnAttribute>() != null))
            {
                prop.SetValue(original, prop.GetValue(actual));
            }
        }
    

    我的意思是,首先从数据库中恢复原始数据,使用该方法将新元素中的所有列属性映射到原始数据,最后进行提交。 我希望这有帮助。

    推荐文章