EF删除具有卸载导航属性的实体

发布于 2024-12-11 06:38:38 字数 1050 浏览 0 评论 0原文

我有一个实体。 授权。每个任务都有一个必需的:与一个人(NavigationProperty)的许多关系。我将 DbContext API 与 (LazyLoadingEnabled、AutoDetectChangesEnabled、ValidateOnSaveEnabled、ProxyCreationEnabled) 结合使用

现在我想删除 Mandate 实体。任务实体由另一个上下文使用 AsNoTracking() 加载。

message.Result.
    ObserveOn(On<DataComposition>.Scheduler).
    Where(r => r).
    Subscribe(_ =>
    {
        using (var unit = UnitOfWork.Begin())
        {
            var mandate = this.SelectedItem.OriginalEntity;

            this.mandateRepository.Attach(mandate);
            // mandate.Person.ToString();

            this.mandateRepository.Delete(mandate);

            unit.Commit();
        }

        this.List.RemoveOnUi(this.SelectedItem);
    });

现在,在提交过程中,我遇到以下异常:“CodeFirstContainer.Mandates”中的实体参与“Mandate_Person”关系。找到 0 个相关的“Mandate_Person_Target”。 1 预计为“Mandate_Person_Target”。

如果我在填充/选择期间包含 Person 属性或者访问该属性(延迟加载),则删除有效,但我不喜欢实现/保留许多实体仅用于删除情况,并且我不喜欢触发对数据库的多个DELETE查询!

I have an Entity. Mandate. Every mandate has a required:many relation to a Person (NavigationProperty). I use the DbContext API with (LazyLoadingEnabled, AutoDetectChangesEnabled, ValidateOnSaveEnabled, ProxyCreationEnabled)

Now I like to delete a Mandate entity. The mandate entities are loaded by another context with AsNoTracking().

message.Result.
    ObserveOn(On<DataComposition>.Scheduler).
    Where(r => r).
    Subscribe(_ =>
    {
        using (var unit = UnitOfWork.Begin())
        {
            var mandate = this.SelectedItem.OriginalEntity;

            this.mandateRepository.Attach(mandate);
            // mandate.Person.ToString();

            this.mandateRepository.Delete(mandate);

            unit.Commit();
        }

        this.List.RemoveOnUi(this.SelectedItem);
    });

Now during committing I get the following exception: Entities in 'CodeFirstContainer.Mandates' participate in the 'Mandate_Person' relationship. 0 related 'Mandate_Person_Target' were found. 1 'Mandate_Person_Target' is expected.

The delete works if I include the Person Property during the population/selection or if I visit the Property (lazyloading), but I DONT LIKE to materialize/hold many entities only for the deletion case and I DONT LIKE to trigger more than a single DELETE query to db!

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

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

发布评论

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

评论(1

猛虎独行 2024-12-18 06:38:38

事实上,如果您填充了导航属性 mandate.Person,以下 SQL 语句……

delete [dbo].[Mandates]
where (([Id] = @0) and ([PersonId] = @1))

将发送到数据库,让我认为导航属性确实必须 填充具有正确 PersonId 的人员以删除父级。

我不知道为什么实体框架不发送带有主键的删除语句……

delete [dbo].[Mandates]
where ([Id] = @0)

正如我所预期的那样。

编辑

如果 Mandate 实体具有 Person 导航属性的外键属性 PersonId,则预期的 SQL(上面的第二个)被发送到数据库。在这种情况下,Person 导航属性可以为 null,并且 FK 属性 PersonId 的值并不重要。

编辑 2

如果您不想引入 FK 属性,则 DB 往返成本最少的方式可能是获取人员的 ID,然后在内存中使用该密钥创建一个虚拟人员:

// ...
var personId = context.Mandates
    .Where(m => m.Id == mandate.Id)
    .Select(m => m.Person.Id)
    .Single();

mandate.Person = new Person { Id = personId };

this.mandateRepository.Attach(mandate);
this.mandateRepository.Delete(mandate);
// ...

The fact that, if you have the navigation property mandate.Person populated, the following SQL statement ...

delete [dbo].[Mandates]
where (([Id] = @0) and ([PersonId] = @1))

... is sent to the database, lets me think that the navigation property indeed must be populated with a person with the correct PersonId to delete the parent.

I have no idea why Entity Framework just doesn't send a delete statement with the primary key ...

delete [dbo].[Mandates]
where ([Id] = @0)

... as I had expected.

Edit

If the Mandate entity has a foreign key property PersonId for the Person navigation property, the expected SQL (the second above) is sent to the database. In this case the Person navigation property can be null and the value of the FK property PersonId doesn't matter.

Edit 2

If you don't want to introduce a FK property the way with the least DB-roundtrip-costs would probably be to fetch the person's Id and then create a dummy person with that key in memory:

// ...
var personId = context.Mandates
    .Where(m => m.Id == mandate.Id)
    .Select(m => m.Person.Id)
    .Single();

mandate.Person = new Person { Id = personId };

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