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

时间:2010-05-20 09:14:55

标签: c# asp.net linq linq-to-sql datacontext

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

  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 个答案:

答案 0 :(得分:9)

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

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 context

调用它

答案 1 :(得分:3)

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

答案 2 :(得分:2)

有关于此主题的讨论here at MSDN s 建议您使用IsVersion字段和Attach方法

答案 3 :(得分:2)

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

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

请注意,要使其正常工作,您需要在表格中使用&#34;版本&#34;类型列#34;时间戳&#34;

答案 4 :(得分:1)

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

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是您的数据库类,根据您的设置,您可能只想做

_dataContext.Attach(entity);

答案 5 :(得分:0)

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

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));
        }
    }

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