Entity Framework 实践系列 —— 搞好关系 - 生儿育女(一对多,one-to-many)

单相思(单向一对一),到两情相悦(双向一对一)并步入婚姻殿堂,接下来就是生儿育女,男人升级为父亲,如果生了很多孩子,那父亲与孩子之间的关系就是“一对多”。

一个父亲有多个孩子,一个孩子只属于一个父亲。

我们还是以博客为例,场景如下:

一个博客(BlogSite)有多篇文章(BlogPost),一篇文章只属于一个博客。

看类图:

看表结构:

BlogSite与BlogPost的定义代码:

复制代码
public class BlogSite
{
public int BlogID { get; set; }
public string BlogApp { get; set; }
public bool IsActive { get; set; }
public Guid UserID { get; set; }
public virtual BlogUser BlogUser { get; set; }
public virtual ICollection<BlogPost> BlogPosts { get; set; }
}
复制代码

public class BlogPost
{
public int ID { get; set; }
public string Title { get; set; }
public int BlogID { get; set; }
public BlogSite BlogSite { get; set; }
}

下面是关键一步,在Entity Framework的OnModelCreating中通过Fluent API定义“一对多”关系:

modelBuilder.Entity<BlogSite>()
.HasMany(b
=> b.BlogPosts)
.WithRequired(p
=> p.BlogSite);

代码简单直观,一个博客HasMany文章,一篇文章Require一个博客。

下面我们通过三个查询场景验证一下。

第一个场景:进入一个博客(BlogSite),并阅读博客中的所有文章(BlogPost)。

LINQ查询代码:

public BlogSite GetBlogSite(int blogId)
{
return _blogSiteReposiotry.Entities
.Include(b
=> b.BlogPosts)
.FirstOrDefault(b
=> b.BlogID == blogId);
}

测试代码:

复制代码
[TestMethod]
public void GetBlogSite_Test()
{
var blogSite
= _aggBlogSiteService.GetBlogSite(1);
Assert.IsNotNull(blogSite);
Console.WriteLine(
"BlogApp:" + blogSite.BlogApp);
Console.WriteLine(
"BlogPosts:");
blogSite.BlogPosts.ToList().ForEach
(
p
=> Console.WriteLine(p.Title + "-" + p.BlogSite.BlogApp)
);
}
复制代码

测试结果:

实际执行的SQL:

这段SQL看似复杂,实际上SQL Server会在执行时进行优化,看执行计划就知道了。

测试符合要求,通过!

第二个场景:阅读一篇文章(BlogPost),并要知道来自哪个博客(BlogSite)

LINQ查询代码:

public BlogPost GetBlogPost(int blogPostId)
{
return _blogPostRepository.Entities
.Include(p
=> p.BlogSite)
.FirstOrDefault(p
=> p.ID == blogPostId);
}

测试代码:

[TestMethod]
public void GetBlogPost_Test()
{
var p
= _aggBlogSiteService.GetBlogPost(1);
Assert.IsNotNull(p);
Console.WriteLine(
"BlogPost Title:" + p.Title + ", " +
"BlogApp:" + p.BlogSite.BlogApp);
}

测试结果:

实际执行的SQL:

测试通过!

第三个场景:看很多文章(BlogPost),并要知道每篇文章分别来自哪个博客(BlogSite)

LINQ查询代码:

public IEnumerable<BlogPost> GetAllBlogPosts()
{
return _blogPostRepository.Entities
.Include(p
=> p.BlogSite);
}

测试代码:

复制代码
[TestMethod]
public void GetBlogPosts_Test()
{
_aggBlogSiteService.GetAllBlogPosts().ToList()
.ForEach(
p
=> Console.WriteLine("BlogPost Title:" + p.Title + ", " +
"BlogApp:" + p.BlogSite.BlogApp)
);
}
复制代码

测试结果:

实际执行的SQL:

轻松过关!

小结

HasMany + WithRequired,“一对多”关系容易理解,实现简单,走的弯路也最少。

只要两情相悦了,一切都变得简单,而最难的就是如何从“单相思”到“两情相悦”。

HasMany
posted @   dudu  阅读(16288)  评论(26编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
历史上的今天:
2007-07-09 给园子里正在创业的朋友推荐一篇文章
2007-07-09 关于引入企业赞助的想法
2007-07-09 博客园的梦想
2004-07-09 新增两个Skin
点击右上角即可分享
微信分享提示