一对多关系中的唯一名称

Unique names within a one to many relationship

我在 Web api 核心 (netcoreapp2.1) 项目中使用 Microsoft.EntityFrameworkCore.Sqlite (2.1.0),以便将 BlogArticle 条目写入一个(SQLite)数据库。他们有一个一对多的关系,我正在用流利的 api 实现这种关系。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<Blog>().HasIndex(b => b.Name).IsUnique();
  modelBuilder.Entity<Blog>().HasMany(b => b.Articles).WithOne().OnDelete(DeleteBehavior.Cascade);
}

这就是 BlogArticle 的 class 定义:

public class Blog
{
    [Required]
    public Guid BlogId { get; set; }
    [Required]
    public String    Name { get; set; }
    public String    Description { get; set; }
    public DateTime Created { get; set; }
    public List<Article> Articles { get; set; }

}

public class Article
{
    [Required]
    public Guid      ArticleId { get; set; }
    [Required]
    public Guid      BlogId   { get; set; }
    [Required]
    public String    Name { get; set; }
    public String    Description { get; set; }
    public DateTime  Created { get; set; }
    public String    Content { get; set; }

}

Article 的下一个要求是在 ("parent") Blog 中有唯一的 Name。所以我不能像这样设置它:

modelBuilder.Entity<Article>().HasIndex(a => a.Name).IsUnique();

以上代码段要求每篇文章在整个数据库中都具有唯一的 Name。我想要的是关于 ("parent") Blog 条目的唯一 Name

我想到的一个解决方案是在编写新的 Article 条目之前明确检查此条件:

[HttpPost("{id}/articles")] // id - is the `Blog` id here
public IActionResult CreateArticle(Guid id, Article article)
{
  List<Article> articles = blogRepository.GetArticlesByBlogId(id);

  // Look up the names of all articles belonging to the affected `Blog`
  if (articles.Any(a => a.Name == article.Name))
  {
    return BadRequest("Article name is not unique!");
  }

  article.ArticleId = new Guid();
  article.BlogId = id;
  article.Created = DateTime.Now;

  blogRepository.AddArticle(article);
  blogRepository.SaveChanges();
  return CreatedAtRoute("GetArticle", new { id = article.ArticleId }, article);
}

我发现这个实现不是很优雅,而且我也很确定必须有另一种方法来实现它。这可以使用 fluent api 来完成吗?除了我的方法还有什么方法?

为了组合 BlogIdName 限制,您可以为 Article 定义一个 Index,如下所示:

        builder.Entity<Blog>().HasIndex(b => b.Name).IsUnique();
        builder.Entity<Blog>().HasMany(b => b.Articles).WithOne().OnDelete(DeleteBehavior.Cascade);
        builder.Entity<Article>().HasIndex(a => new { a.Name, a.BlogId }).IsUnique();