如何在ASP.NET Core+EF中实现作者名与所属书名的唯一性约束?
实现作者名称与所属书籍名称不同的验证规则
一、应用层代码验证
因为要关联Book实体的属性做跨实体验证,默认数据注解无法直接实现,需要自定义验证属性:
using System.ComponentModel.DataAnnotations; public class AuthorNameNotEqualToBookNameAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var author = validationContext.ObjectInstance as Author; if (author == null || author.Book == null) { // 若Book未提前加载,可根据业务需求选择跳过验证或抛出异常 return ValidationResult.Success; } if (string.Equals(author.Name, author.Book.Name, StringComparison.OrdinalIgnoreCase)) { return new ValidationResult("作者名称不能与所属书籍名称相同"); } return ValidationResult.Success; } }
然后在Author模型的Name属性上标记该特性:
class Author { public int Id { get; set; } [AuthorNameNotEqualToBookName] public string Name { get; set; } public int BookId { get; set; } // 显式添加外键属性,后续数据库约束需要用到 public Book Book { get; set; } }
注意:创建作者时,要确保服务层已提前查询对应
Book并赋值给Author.Book,否则验证会失效。
二、数据库层约束(通过OnModelCreating实现)
为了从数据库层面保证数据一致性,在DbContext的OnModelCreating方法中添加检查约束:
using Microsoft.EntityFrameworkCore; public class YourDbContext : DbContext { public DbSet<Book> Books { get; set; } public DbSet<Author> Authors { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置Book与Author的一对多关系(EF未自动识别时手动配置) modelBuilder.Entity<Author>() .HasOne(a => a.Book) .WithMany(b => b.Authors) .HasForeignKey(a => a.BookId); // 添加数据库检查约束:作者名称不等于所属书籍名称 modelBuilder.Entity<Author>() .ToTable(t => t.HasCheckConstraint("CK_Author_Name_Not_Equal_Book_Name", "[Name] != (SELECT [Name] FROM [Books] WHERE [Id] = [BookId])")); } }
最后步骤
添加约束后,需要生成迁移并更新数据库,让约束生效:
Add-Migration AddAuthorBookNameCheckConstraint Update-Database
内容的提问来源于stack exchange,提问作者user467566
相关产品推荐
相关产品推荐

