我正在嘗試編寫一個使用Linq-to-SQL與數據庫接口的程序(MS SQL Server 2008)。添加和刪除似乎沒問題,但我無法繞過更新。使用Linq-to-SQL更新實體 - 附加一個不是新的實體
該實體上有一個版本列,它是數據庫上的時間戳列,用於內置於Linq-to-SQL的樂觀鎖定。我已將實體上的所有字段的更新檢查屬性設置爲從不。
我有以下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;
}
}
在線指示,我得到以下異常:
的嘗試已經取得了附加或 加入,是不是新的實體,也許 已經從另一個 的DataContext裝。這不支持。
我不明白爲什麼我在傳遞原始版本的實體時得到這個異常。如果我將註釋行更改爲
_dataContext.Tasks.Attach(task, true);
任何幫助將不勝感激。
更新
我已經作出了庫實現IDisposable和改變無處不在調用構造函數中使用的using (TaskRepository taskRepository = new TaskRepository)
。在TaskRepository
的Dispose()
方法中,我在我的數據上下文中調用了Dispose()
。
我也改變了Update()
方法在我的Task對象上調用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
}
的任務分離()方法是這樣的:
public void Detach()
{
this._Project = default(EntityRef<Project>);
this._Priority = default(EntityRef<Priority>);
}
僅供參考,我的實體是這樣的:
我現在在所示的線上獲得以下例外。
無法添加具有已使用密鑰的實體。
我已將原始帖子更新爲帶有從該鏈接找到的建議的新代碼。我現在得到了一個不同的例外。你能幫我嗎? – Stu 2011-05-08 14:36:49
好的..嘗試爲每個查詢使用新的datacontext ..共享datacontext不是最好的選擇,如果你附加和deattach對象.. – 2011-05-08 22:14:42