EFCore_一对一、一对多、多对多

一对一、一对多、多对多

何处配置:实体配置类(以一对一为例)

如何配置
一对一:HasOne().WithOne()
关系配置在任意一端均可,但需要显式地在该端对应的实体类中声明一个外键属性,并通过HasForeignKey<T>()显式指定(需要泛型以说明外键属性所在的实体类,此处无法推断类型)

internal class DeliveryConfig : IEntityTypeConfiguration<Delivery>
{
    public void Configure(EntityTypeBuilder<Delivery> builder)
    {
        builder.HasOne(d => d.TheOrder).WithOne(o => o.TheDelivery).HasForeignKey<Delivery>(d => d.OrderId);
    }
}

实体
通过Order.TheDelivery与Delivery.TheOrder构建一对一的关系(属性名无强制要求)

internal class Order
{
    public int Id { get; set; }
    public string OrderName { get; set; }
    public int OrderNumber { get; set; }
    public Delivery TheDelivery { get; set; }
}
internal class Delivery
{
    public int Id { get; set; }
    public string CompanyName { get; set; }
    public int DeliveryNumber { get; set; }
    public Order TheOrder { get; set; }
    public int OrderId { get; set; }
}

一对多:HasOne().WithMany() 或 HasMany().WithOne()
关系原则上配置在任意一端均可,但推荐配置在"多"端。此外,外键生成在"多"端对应的表,不显式声明外键属性并指定时,默认生成的字段名为"实体类名Id"

internal class CommentConfig : IEntityTypeConfiguration<Comment>
{
    public void Configure(EntityTypeBuilder<Comment> builder)
    {
        builder.HasOne(c => c.TheArticle).WithMany(a => a.Comments);
    }
}

实体不再赘述,"多"端实体类中的"一"端属性类型为List<T> 

多对多:HasMany().WithMany()
关系配置在任意一端均可,实体对应的表中不存储外键(无需,也无法调用HasForeignKey<T>()),外键存储在额外生成的中间表中,可通过UsingEntity("xxx")或UsingEntity(t=>t.ToTable("xxx"))来指定中间表名

internal class StudentConfig : IEntityTypeConfiguration<Student>
{
    public void Configure(EntityTypeBuilder<Student> builder)
    {
        builder.HasMany(s => s.Teachers).WithMany(t => t.Students).UsingEntity(e => e.ToTable("relation_student_teacher"));
    }
}

单向导航属性 

上文示例中的Order.TheDelivery与Delivery.TheOrder为双向导航属性,简而言之就是Order与Delivery都知道对方的存在,而出现仅一方知道另一方的存在时,称该方实体类中的另一方属性为单向导航属性

问:单向导航属性存在的意义是什么?
答:避免字段膨胀 与 利好数据增减
以"教师"实体为例,其对应表为"Teacher"。除了实体的基础数据,还有教师审批的表格、教师批阅的试卷等等数据与实体相关联,但若将这些数据一同储存在Teacher表中势必会导致Teacher表的字段膨胀,并且与实体相关联的数据发生变动时需要直接修改表的字段

问:如何定义单向导航属性?
答:通常单向导航属性出现在一对一 / 一对多的情况下(多对多的情况下外键储存在中间表),所以将关系配置在单向导航属性所在的实体类的配置类中,并将WithOne() / WithMany()置空即可

联表查询

var result = dbContext.Students.Include(s => s.Teachers);

注:使用Select()会隐式调用Include() 

新增数据时,数据之间存在关联,不需要对所有导航属性赋值,也不需要对所有实例Add

简而言之,EFCore能顺藤摸瓜

Article article = new() { Title = "文章标题", Text = "震惊!......", AuthorName = "汤姆" };

Comment comment_1 = new() { Content = "一楼" };
Comment comment_2 = new() { Content = "二楼" };
Comment comment_3 = new() { Content = "三楼" };

article.Comments.Add(comment_1);
article.Comments.Add(comment_2);
article.Comments.Add(comment_3);

dbContext.Articles.Add(article);

dbContext.SaveChanges();    

上述代码中,article的导航属性Comments被添加了Comment实例,令article与comment_1、comment_2、comment_3产生了关联,所以在dbContext.Articles.Add(article)时,EFCore根据article的导航属性Comments找到Comment实例,并为Comment实例的导航属性赋值(值为article),并将Comment实例一齐Add

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用EF Core进行多表联查时,可以使用LINQ提供的多种方法来实现排序操作。根据你提供的引用内容,可以使用`orderby`关键字来对查询结果进行排序。在LINQ查询中,可以使用`orderby`关键字后跟着要排序的字段,使用`ascending`或`descending`关键字来指定升序或降序排序。 例如,如果你想对查询结果按照`CREATETIME`字段进行降序排序,可以使用以下代码: ``` var query = (from exam in context.ExamineUser orderby exam.CREATETIME descending select new ExamineUserEntity { }).Skip(pageindex * pagesize) .Take(pagesize) .ToList(); ``` 在这个例子中,我们使用了`orderby`关键字后跟着要排序的字段`exam.CREATETIME`,并使用`descending`关键字表示按照降序排列。最后使用了`Skip`和`Take`方法实现了分页功能。 需要注意的是,以上代码中的`context.ExamineUser`是一个示例,你需要根据自己的数据库结构和实体类来替换成相应的查询语句。 希望这个回答对你有帮助。如果你有更多的问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [EF框架下 Linq语句多表联查排序实例](https://blog.csdn.net/weixin_30813225/article/details/98783719)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [EFCore 关联表查询_多表使用整理](https://blog.csdn.net/u011127019/article/details/123595207)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值