在我的数据库中,我想创建一个使用代码优先方法两次引用另一个表的表。这是代码:
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; }
}
我觉得评论不允许进行适当的沟通,所以我无法全面了解情况。
基本上,该问题是由于 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; }
}