C# 使用Linq到SQL更新实体-附加非新实体

C# 使用Linq到SQL更新实体-附加非新实体,c#,linq-to-sql,repository,C#,Linq To Sql,Repository,我正在尝试编写一个程序,使用LINQtoSQL与数据库进行接口(MSSQLServer2008)。添加和删除似乎还可以,但我无法了解更新 实体上有一个version列,它是数据库上的一个timestamp列,用于linqtosql中内置的乐观锁定。我已将实体上所有字段的Update Check属性设置为Never 我有以下SaveTaskCommand,用于插入和更新实体,具体取决于特定任务是否已添加到数据库中 public class SaveTaskCommand : CustomComma

我正在尝试编写一个程序,使用LINQtoSQL与数据库进行接口(MSSQLServer2008)。添加和删除似乎还可以,但我无法了解更新

实体上有一个version列,它是数据库上的一个timestamp列,用于linqtosql中内置的乐观锁定。我已将实体上所有字段的Update Check属性设置为Never

我有以下SaveTaskCommand,用于插入和更新实体,具体取决于特定任务是否已添加到数据库中

public class SaveTaskCommand : CustomCommand
{
    private Task _task;
    private TaskDetailsViewModel _taskDetails;

    public SaveTaskCommand(Task task, TaskDetailsViewModel taskDetails)
    {
        _task = task;
        _taskDetails = taskDetails;
    }

    public override void Execute(object parameter)
    {
        TaskRepository taskRepository = new TaskRepository();
        if (!taskRepository.ContainsTask(_task))
        {
            taskRepository.AddTask(_task);
            _taskDetails.Mediator.NotifyColleagues(ViewModelMessages.TaskAdded, 
                _task);
        }
        else
        {
            taskRepository.UpdateTask(_task);
            _taskDetails.Mediator.NotifyColleagues(
                ViewModelMessages.TaskAmended, null);
        }
    }

    public override bool CanExecute(object parameter)
    {
        return _task.IsValid();
    }
}
CustomCommand类只是一个封装ICommand并处理CanExecuteChanged事件的类,因此我不必在每个命令中重复代码

如您所见,TaskRepository是在命令的Execute()方法中创建的,该方法首先检查任务是否已在数据库中,然后选择是插入还是更新。TaskRepository的代码如下所示

public class TaskRepository : IRepository
{
    private DataContextDataContext _dataContext;

    public TaskRepository()
    {
        _dataContext = new DataContextDataContext();
    }

    public List<Task> GetAllTasks()
    {
        return _dataContext.Tasks.ToList();
    }

    public Task GetForKeyTable(int keyTable)
    {
        return _dataContext.Tasks.Where(t => t.KeyTable == keyTable).
            FirstOrDefault();
    }

    public void AddTask(Task task)
    {
        task.Project = _dataContext.Projects.SingleOrDefault(
            p => p.KeyTable == task.KeyProject);
        _dataContext.Tasks.InsertOnSubmit(task);
        _dataContext.SubmitChanges();

    }

    public void UpdateTask(Task task)
    {
        //exception occurs here
        _dataContext.Tasks.Attach(task, GetForKeyTable(task.KeyTable)); 
        _dataContext.SubmitChanges();
    }

    public void DeleteTask(Task task)
    {
        _dataContext.Tasks.Attach(task, GetForKeyTable(task.KeyTable));
        _dataContext.Tasks.DeleteOnSubmit(task);
        _dataContext.SubmitChanges();
    }

    public bool ContainsTask(Task task)
    {
        return GetForKeyTable(task.KeyTable) != null;
    }
}
任何帮助都将不胜感激

更新

我已使我的存储库实现IDisposable并在调用构造函数的任何地方进行更改,使用(TaskRepository TaskRepository=new TaskRepository)。在
TaskRepository
Dispose()
方法中,我在数据上下文中调用了
Dispose()

我还将
Update()
方法更改为在我的任务对象上调用
Detach()
。我的代码现在如下所示:

public class TaskRepository : IRepository, IDisposable
{
    private DataContextDataContext _dataContext;

    public TaskRepository()
    {
        _dataContext = new DataContextDataContext();
        DataLoadOptions dlo = new DataLoadOptions();
        dlo.LoadWith<Task>(t => t.Project);
        dlo.LoadWith<Task>(t => t.Priority);
        _dataContext.LoadOptions = dlo;
    }

    public List<Task> GetAllTasks()
    {
        return _dataContext.Tasks.ToList();
    }

    public Task GetForKeyTable(int keyTable)
    {
        return _dataContext.Tasks.Where(t => t.KeyTable == keyTable).FirstOrDefault();
    }

    public void AddTask(Task task)
    {
        task.Project = _dataContext.Projects.SingleOrDefault(p => p.KeyTable == task.KeyProject);
        _dataContext.Tasks.InsertOnSubmit(task);
        _dataContext.SubmitChanges();

    }

    public void UpdateTask(Task task)
    {
        task.Detach();

        _dataContext.Tasks.Attach(task, true);  //exception occurs here
        _dataContext.Refresh(RefreshMode.KeepCurrentValues, task);
        _dataContext.SubmitChanges();
    }

    public void DeleteTask(Task task)
    {
        _dataContext.Tasks.Attach(task, GetForKeyTable(task.KeyTable));
        _dataContext.Tasks.DeleteOnSubmit(task);
        _dataContext.SubmitChanges();
    }

    public bool ContainsTask(Task task)
    {
        return GetForKeyTable(task.KeyTable) != null;
    }

    #region IDisposable Members

    public void Dispose()
    {
        _dataContext.Dispose();
    }

    #endregion
}
公共类任务存储库:IRepository,IDisposable
{
私有DataContextDataContext_dataContext;
公共任务库()
{
_dataContext=新的DataContextDataContext();
DataLoadOptions dlo=新的DataLoadOptions();
dlo.LoadWith(t=>t.Project);
dlo.LoadWith(t=>t.Priority);
_dataContext.LoadOptions=dlo;
}
公共列表GetAllTasks()
{
return_dataContext.Tasks.ToList();
}
公共任务GetForKeyTable(int-keyTable)
{
返回_dataContext.Tasks.Where(t=>t.KeyTable==KeyTable.FirstOrDefault();
}
公共无效添加任务(任务任务)
{
task.Project=\u dataContext.Projects.SingleOrDefault(p=>p.KeyTable==task.KeyProject);
_dataContext.Tasks.InsertOnSubmit(任务);
_dataContext.SubmitChanges();
}
公共无效更新任务(任务)
{
task.Detach();
_dataContext.Tasks.Attach(task,true);//此处发生异常
_刷新(RefreshMode.KeepCurrentValues,任务);
_dataContext.SubmitChanges();
}
公共无效删除任务(任务任务)
{
_task.Attach(task,GetForKeyTable(task.KeyTable));
_dataContext.Tasks.deleteoSubmit(任务);
_dataContext.SubmitChanges();
}
公共bool CONTANSTASK(任务)
{
返回GetForKeyTable(task.KeyTable)!=null;
}
#区域IDisposable成员
公共空间处置()
{
_Dispose();
}
#端区
}
任务上的Detach()方法如下所示:

public void Detach()
{
    this._Project = default(EntityRef<Project>);
    this._Priority = default(EntityRef<Priority>);
}
public void Detach()
{
此._项目=默认值(EntityRef);
此._Priority=default(EntityRef);
}
作为参考,我的实体如下所示:

public class TaskRepository : IRepository, IDisposable
{
    private DataContextDataContext _dataContext;

    public TaskRepository()
    {
        _dataContext = new DataContextDataContext();
        DataLoadOptions dlo = new DataLoadOptions();
        dlo.LoadWith<Task>(t => t.Project);
        dlo.LoadWith<Task>(t => t.Priority);
        _dataContext.LoadOptions = dlo;
    }

    public List<Task> GetAllTasks()
    {
        return _dataContext.Tasks.ToList();
    }

    public Task GetForKeyTable(int keyTable)
    {
        return _dataContext.Tasks.Where(t => t.KeyTable == keyTable).FirstOrDefault();
    }

    public void AddTask(Task task)
    {
        task.Project = _dataContext.Projects.SingleOrDefault(p => p.KeyTable == task.KeyProject);
        _dataContext.Tasks.InsertOnSubmit(task);
        _dataContext.SubmitChanges();

    }

    public void UpdateTask(Task task)
    {
        task.Detach();

        _dataContext.Tasks.Attach(task, true);  //exception occurs here
        _dataContext.Refresh(RefreshMode.KeepCurrentValues, task);
        _dataContext.SubmitChanges();
    }

    public void DeleteTask(Task task)
    {
        _dataContext.Tasks.Attach(task, GetForKeyTable(task.KeyTable));
        _dataContext.Tasks.DeleteOnSubmit(task);
        _dataContext.SubmitChanges();
    }

    public bool ContainsTask(Task task)
    {
        return GetForKeyTable(task.KeyTable) != null;
    }

    #region IDisposable Members

    public void Dispose()
    {
        _dataContext.Dispose();
    }

    #endregion
}

我现在在指定的行中得到以下异常

无法添加密钥已在使用中的实体


在将
任务
对象附加到新对象之前,请尝试从以前的数据上下文中取消附加该对象,或者在整个应用程序中使用数据上下文的单个实例


您可以在这里找到deattach方法的示例:

我用新代码更新了原始帖子,并从该链接中找到了建议。我现在有一个不同的例外。你能帮忙吗?好的。。尝试为每个查询使用新的datacontext。。如果附加和取消附加对象,则共享datacontext不是最佳选项。。