2011-05-21 64 views
1

我目前無法理解爲什麼我的樣式實體存儲庫中的更新方法在我的Linq到SQL域模型層中引發NullReferenceException。問題似乎是,我正在更新的Style對象上的EntitySet<Product> Product屬性在必需使用Detach方法後爲null。在提交更改之前,實際的異常將被拋到附件上。Linq到SQL更新 - 更新後的NullReferenceException以下分離

我的更新只是爲了定位樣式表,產品引用不應該真的進入它,但關係被映射到由SQLMetal生成的代碼中,這是我的應用程序設計的重要部分。

如果我刪除外鍵關係,重新創建映射類並相應地調整代碼,問題就會消失。不過,如果可能的話,我會想要保持外鍵的關係。

我會嘗試更好地解釋設置:

在SQL服務器數據庫中的關係是像這樣,在產品表中引用樣式表:

enter image description here

實體映射類是用SQLMetal創建的,據我所知,沒有什麼不尋常的方式產生。

的更新方法是:

public Style Update(Style style) 
    { 
     using (var dc = new ProjectERPDataContext(Config.ConnectionStringERPDB)) 
     { 
      style.Detach(); 

      dc.Style.Attach(style); 
      dc.Refresh(RefreshMode.KeepCurrentValues, style); 
      dc.SubmitChanges(); 

      return style; 
     } 
    } 

的分離方法被保持在一個局部類:

的分離方法中存在,因爲如果沒有,則拋出異常:「試圖具有被添加或附加一個不是新的實體,可能是從另一個DataContext加載的,不支持。「

public partial class Style 
{ 
    public void DetachEntityRefs() 
    { 
     this._Product = default(EntitySet<Product>); 
    } 
} 

實體類開始,如:

[Table(Name="dbo.Style")] 
public partial class Style : INotifyPropertyChanging, INotifyPropertyChanged 
{ 

    private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); 

    private int _ID; 

    private string _Name; 

    private EntitySet<Product> _Product; 

所以,你可以清楚地看到異常被拋出:

enter image description here

完整的堆棧跟蹤:

System.NullReferenceException : Object reference not set to an instance of an object. 
at System.Data.Linq.Mapping.EntitySetDefSourceAccessor`2.GetValue(T instance) 
at System.Data.Linq.Mapping.MetaAccessor`2.GetBoxedValue(Object instance) 
at System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.HasDeferredLoader(MetaDataMember deferredMember) 
at System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.get_HasDeferredLoaders() 
at System.Data.Linq.ChangeTracker.StandardChangeTracker.Track(MetaType mt, Object obj, Dictionary`2 visited, Boolean recurse, Int32 level) 
at System.Data.Linq.ChangeTracker.StandardChangeTracker.Track(Object obj, Boolean recurse) 
at System.Data.Linq.Table`1.Attach(TEntity entity, Boolean asModified) 
at ProjectERP.DomainModel.Repositories.SQLStyleRepo.Update(Style style) in SQLStyleRepo.cs: line 45 
at ProjectERP.UnitTests.DomainModel.SQLStyleRepoTests.Test_can_update_style() in SQLStyleRepoTests.cs: line 67 
+0

,你能否告訴我們,異常的堆棧跟蹤? – Steven 2011-05-21 10:13:39

+0

只需加入。不會太多! – gb2d 2011-05-21 10:17:28

回答

3

我敢打賭,原因是這個定時炸彈你栽在這裏:

this._Product = default(EntitySet<Product>); 

default(EntitySet<Product>)null。嘗試將它設置爲東西

this._Product = new EntitySet<Product>(); 
+0

謝謝,這讓我的測試通過。我還在建立我對Linq-SQL的理解。你能解釋爲什麼我不得不將這個設置爲新的而不是默認的。對於其他類,我已成功使用默認值(EntityRef )。我想這裏的區別是這是一個EntitySet,而不是EntityRef?我不想在我的應用程序中使用任何「Timebombs」!我的理解迄今來自:http://geekswithblogs.net/michelotti/archive/2007/12/25/117984.aspx – gb2d 2011-05-21 10:27:48

+1

@BombDefused :(哇,剛剛注意到你的屏幕名稱,Timebomb不是雙關語)因爲L2S預計在那裏找到一個集合,即使是空的。 'null'不是一個空集,而是一個集的缺失。這就是你得到NullReferenceException的原因。在EntityRefs中,L2S預計會有或沒有參考。它使用'null'。不要問爲什麼,我沒有設計它。 – 2011-05-21 10:30:52