Linq到SQL更新 - 在Detach之后更新时出现NullReferenceException

时间:2011-05-21 10:04:10

标签: linq linq-to-sql linq-to-entities

我目前无法理解为什么我的存储库中的样式实体的更新方法在我的Linq to SQL域模型层中抛出了NullReferenceException。问题似乎是,在必要时使用Detach方法后,我正在更新的Style对象上的EntitySet<Product> Product属性为null。在提交更改之前,会在附件上抛出实际的异常。

我的更新只是针对Style表,Product引用不应该真正进入它,但是关系映射到SQLMetal生成的代码中,这是我的应用程序设计的一个重要部分。

如果删除外键关系,重新创建映射类并相应地调整代码,问题就会消失。但是,如果可能的话,我想关注忘记密钥关系。

我将尝试最好地解释设置:

SQL Server数据库中的关系是这样的,Product表引用了Style表:

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 

1 个答案:

答案 0 :(得分:3)

我敢打赌原因就是你在这里播下的定时炸弹:

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

default(EntitySet<Product>)null。尝试将其设置为某事

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