Linq to SQL 更新 - 分离后更新时出现 NullReferenceException

发布于 2024-11-08 16:25:07 字数 2722 浏览 0 评论 0原文

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

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

如果我删除外键关系,重新创建映射类并相应地调整代码,问题就会消失。不过,如果可能的话,我想保留外键关系。

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

SQL Server 数据库中的关系如下所示,产品表引用样式表:

在此处输入图像描述

实体映射类是使用 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;

因此您可以准确地看到抛出异常的位置:

在此处输入图像描述

完整堆栈跟踪:

    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 

I can't currently understand why my update method in my repository for the style entity is throwing a NullReferenceException in my Linq to SQL domain model layer. The problem seems to be that the EntitySet<Product> Product property on the Style object that I am updating is null following the necessary use of a Detach method. The actual exception is thrown on the attach prior to the submission of changes.

My update is only meant to target the Style table, the Product reference should not really come into it, but the relationship is mapped in the code generated by SQLMetal, which is an important part of my application design.

If I delete the foreign key relationship, recreate the mapping class and adjust code accordingly, the problem goes away. I would however like to kep the forign key relationship if possible.

I will attempt to best explain the set up:

The relationship in the SQL server database is like so, with the Product table referencing the Style table:

enter image description here

The entity mapping class is created with SQLMetal, as far as I know, there is nothing unusual in the way this is generated.

The update method is:

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;
        }
    }

The detach method is kept in a partial class:

The detach method exists because without, the exception is thrown: "An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported."

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

The entity class starts like:

[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;

So you can see exactly where the exception is thrown:

enter image description here

Full stack trace:

    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 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

守护在此方 2024-11-15 16:25:07

我敢打赌,原因是您在这里埋下了这个定时炸弹:

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

default(EntitySet)null。尝试将其设置为某物

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

I bet the cause is this timebomb you planted here:

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

default(EntitySet<Product>) is null. Try setting it to something:

this._Product = new EntitySet<Product>();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文