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

我可以更新下面函数中给出的员工记录,还是首先要查询员工集合,然后更新数据?

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加载。 这不受支持。

我找到以下解决此问题的方法:

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); } } 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上下文调用它

如果没有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(); } 

这里有关于此主题的讨论,MSDN建议您使用IsVersion字段和Attach方法

您可以使用此重载附加未附加的已修改实体:

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

请注意,要使其正常工作,您需要在表中添加“timestamp”类型的“Version”列

这是我的Repository类中的一个函数,我用它来更新实体

 protected void Attach(TEntity entity) { try { _dataContext.GetTable().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是您的数据库类,根据您的设置,您可能只想这样做

 _dataContext.Attach(entity); 

使用此extend方法更新作为列属性的所有属性:

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

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