EFCore:两次引用另一个表会导致循环或多级联路径错误

问题描述 投票:0回答:1

在我的数据库中,我想创建一个使用代码优先方法两次引用另一个表的表。这是代码:

public class ArticleWord
{
    public long ID  { get; set; }
    public Article? Article { get; set; }
    public virtual Word Word { get; set; }
    public virtual Word WordTarget { get; set; }

    [ForeignKey(nameof(Word))]
    public long WordId { get; set; }

    [ForeignKey(nameof(WordTarget))]
    public long WordTargetId { get; set; }
}

我成功创建了迁移,但是当我更新数据库时出现此错误

Failed executing DbCommand (107ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [ArticleWords] (
    [ID] bigint NOT NULL IDENTITY,
    [ArticleID] bigint NULL,
    [WordId] bigint NOT NULL,
    [WordTargetId] bigint NOT NULL,
    [CreatedAt] datetime2 NOT NULL,
    [CreatedBy] nvarchar(max) NULL,
    [ModifiedAt] datetime2 NULL,
    [ModifiedBy] nvarchar(max) NULL,
    [IsDeleted] bit NOT NULL,
    CONSTRAINT [PK_ArticleWords] PRIMARY KEY ([ID]),
    CONSTRAINT [FK_ArticleWords_Articles_ArticleID] FOREIGN KEY ([ArticleID]) REFERENCES [Articles] ([ID]),
    CONSTRAINT [FK_ArticleWords_Words_WordId] FOREIGN KEY ([WordId]) REFERENCES [Words] ([ID]) ON DELETE CASCADE,
    CONSTRAINT [FK_ArticleWords_Words_WordTargetId] FOREIGN KEY ([WordTargetId]) REFERENCES [Words] ([ID]) ON DELETE CASCADE
);
Microsoft.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 
'FK_ArticleWords_Words_WordTargetId' on table 'ArticleWords' may cause cycles or multiple cascade paths. 
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

如何更改代码才能读取

Word
两次?

更新

我更新了模型,但遇到了同样的错误

[Table("ArticleWords")]
public class ArticleWord : Table
{
    [JsonPropertyName("article")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public Article? Article { get; set; }

    [JsonPropertyName("word")]
    public Word Word { get; set; }

    [JsonPropertyName("wordTarget")]
    public Word WordTarget { get; set; }
} 
c# entity-framework-core
1个回答
0
投票

我觉得评论不允许进行适当的沟通,所以我无法全面了解情况。

基本上,该问题是由于 SQL Server 中有关级联删除操作的限制造成的。

每个外键都有自己的级联删除操作,SQL Server 试图确保删除记录不会导致存在多个删除路径的情况,因为这可能会导致意外的级联效应。

您的原始模型是这样构建的,如果您要从

Words
表中删除一条记录,它可能会通过两个外键约束来级联删除
ArticleWords
表中的记录,从而为级联删除创建多个路径。

该模型定义了

Word
WordTarget
的导航属性,两者都引用
Word
实体,并为
WordId
WordTargetId
建立外键。

public class ArticleWord
{
    public long ID  { get; set; }
    public Article? Article { get; set; }
    public virtual Word Word { get; set; }
    public virtual Word WordTarget { get; set; }

    [ForeignKey(nameof(Word))]
    public long WordId { get; set; }

    [ForeignKey(nameof(WordTarget))]
    public long WordTargetId { get; set; }
}

您的问题是“一种或另一种”类型的情况,您需要使用导航属性 OR

[ForeignKey]
装饰属性。当您这样做时,级联删除问题就会消失。

因此以下任一模型都应该有效:

// Using navigation properties.
public class ArticleWord
{
    public long ID  { get; set; }
    public Article? Article { get; set; }
    public virtual Word Word { get; set; }
    public virtual Word WordTarget { get; set; }
}

// Using [ForeignKey]
public class ArticleWord
{
    public long ID  { get; set; }
    public Article? Article { get; set; }

    [ForeignKey(nameof(Word))]
    public long WordId { get; set; }

    [ForeignKey(nameof(WordTarget))]
    public long WordTargetId { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.