2010-05-12 44 views
1

我已經得到幾個錯誤:linq-to-sql「試圖添加或添加一個不是新的實體」?

  1. 不能用鑰匙已在使用

  2. 的嘗試已經取得了附加或添加,是不是新的實體添加一個實體,也許已經從另一個數據上下文加載

在情況1中,這起源於試圖爲實體設置密鑰而不是實體。在案例2中,我沒有附加實體,但我這樣做:

MyParent.Child = EntityFromOtherDataContext;

我一直在使用使用datacontext包裝一切的模式。就我而言,我在Web表單場景中使用它,顯然將datacontext對象移動到類成員變量可以解決此問題。

我的問題是這樣2倍:

  1. 我怎樣才能擺脫這些錯誤,並沒有構建我的程序在一種奇怪的方式或通過周圍DataContext的同時保持與本地包裝模式?我假設我可以再次擊中數據庫,但這似乎效率很低。

  2. 大多數人會推薦將數據上下文移動到類的範圍對於網頁是可取的嗎?

回答

3
  1. LINQ到SQL是不適應斷開連接的情況。您可以將您的實體複製到與實體具有相似結構的DTO,然後將其傳遞。然後,在將屬性附加到新的數據上下文時,將屬性複製回實體。在附加到新的數據上下文之前,您還可以對實體進行反序列化/重新串行化以獲得乾淨的狀態。第一個解決方法顯然違反了DRY原則,而第二個解決方案只是醜陋的。如果你不想使用任何這些解決方案,剩下的唯一選擇是通過點擊數據庫來檢索你將要通過其PK修改的實體。這意味着每次更新之前都會有一個附加查詢或者如果這是您的選擇,請使用其他ORM。實體框架4(包含在.NET 4中)和自我跟蹤實體是我目前在Web表單項目中使用的,到目前爲止一切都很好。

  2. DataContext不是線程安全的,只能在方法級別與using一起使用,就像您已經這樣做了。您可以考慮將鎖添加到靜態數據上下文,但這意味着無法併發訪問數據庫。另外,你會在上下文中獲得積累在內存中的實體,這會變成潛在的問題。

+0

謝謝!非常好的答案!但是,我正在考慮在網絡表單場景中分享它可能是合適的。 – 2010-05-12 19:35:56

2

對於那些後我來了,我會提供我自己的看法:

「的嘗試已經取得了補充或附加,是不是新的實體」,從這一操作莖錯誤:

Child.Parent = ParentEntityFromOtherDataContext 

我們可以使用當前的DataContext,以避免這樣的問題重新加載對象:

Child.Parent = dc.Entries.Select(t => t).Where(t => t.ID == parentEntry.ID).SingleOrDefault(); 

人能做到這一點

MySubroutine(DataContext previousDataContext) 
{ 
work... 
} 

或Web形成的情況下,我倚使DataContext的一類成員像這樣:

DataContext _dc = new DataContext(); 

是,在DataContext是假設代表工作單位。但是,它是一個輕量級對象,並且在網頁形式非常短暫的情況下,可以將模式從(使用dc = new dc())更改爲僅使用成員變量_dc。我傾向於最後一個解決方案,因爲它將減少數據庫並且需要更少的代碼。

但是,即使這個解決方案有問題嗎?我正在考慮緩存一些陳舊的數據。

1

我最常做的就是這個

public abstract class BaseRepository : IDisposable 
{ 
    public BaseRepository(): 
     this(new MyDataContext(ConfigurationManager.ConnectionStrings["myConnection"].ConnectionString)) 
    { 
    } 

    public BaseRepository(MyDataContext dataContext) 
    { 
     this.DataContext = dataContext; 
    } 

    public MyDataContext DataContext {get; set;} 

    public void Dispose() 
    { 
     this.DataContext.Dispose(); 
    } 
} 

然後想象我有以下的庫

public class EmployeeRepository : BaseRepository 
{ 
    public EmployeeRepository():base() 
    { 
    } 

    public EmployeeRepository(MyDataContext dataContext):base(dataContext) 
    { 
    } 

    public Employee SelectById(Guid id) 
    { 
      return this.DataContext.Employees.FirstOrDefault(e=>e.Id==id); 
    } 

    public void Update(Employee employee) 
    { 
     Employee original = this.Select(employee.Id); 
     if(original!=null) 
     { 
      original.Name = employee.Name; 
      //others 
      this.DataContext.SubmitChanges(); 
     } 
    } 
} 

而在我的控制器(我使用asp.net的MVC)

public ActionResult Update(Employee employee) 
{ 
    using(EmployeeRepository employeeRepository = new EmployeeRepository()) 
    { 
     if(ModelState.IsValid) 
     { 
      employeeRepository.Update(employee); 
     } 
    } 

    //other treatment 
} 

因此datacontext被妥善處置,我可以在我的員工存儲庫的同一個實例中使用它

現在想象一下,對於一個具體的行動我想員工的公司被加載(爲了在我看來以後要持續顯示),我可以這樣做:

public ActionResult Select(Guid id) 
{ 
    using(EmployeeRepository employeeRepository = new EmployeeRepository()) 
    { 
     //Specifying special load options for this specific action: 
     DataLoadOptions options = new DataLaodOptions(); 
     options.LoadWith<Employee>(e=>e.Company); 
     employeeRepository.DataContext.LoadOptions = options; 

     return View(employeeRepository.SelectById(id)); 
    } 
} 
+0

Thanks!相當有用和詳細,我會如何做一個商務課,但爲我的需要矯枉過正,除非我想添加緩存,嗯 – 2010-05-12 19:35:01

相關問題