一对多关系中的唯一名称
Unique names within a one to many relationship
我在 Web api 核心 (netcoreapp2.1) 项目中使用 Microsoft.EntityFrameworkCore.Sqlite
(2.1.0),以便将 Blog
和 Article
条目写入一个(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);
}
这就是 Blog
和 Article
的 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 来完成吗?除了我的方法还有什么方法?
为了组合 BlogId
和 Name
限制,您可以为 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();
我在 Web api 核心 (netcoreapp2.1) 项目中使用 Microsoft.EntityFrameworkCore.Sqlite
(2.1.0),以便将 Blog
和 Article
条目写入一个(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);
}
这就是 Blog
和 Article
的 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 来完成吗?除了我的方法还有什么方法?
为了组合 BlogId
和 Name
限制,您可以为 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();