详解EFCore中的导航属性

2022-07-23,,,

  使用了这么久的entityframeworkcore框架,今天想来就其中的一个部分来做一个知识的梳理,从而使自己对于整个知识有一个更加深入的理解,如果你对efcore中的实体关系不熟悉你需要有一个知识的预热,这样你才能够更好的去理解整个知识,在建立好了这些实体之间的关系以后,我们可以通过使用include、theninclude这些方法来进行快速获得对应关联实体数据,用起来确实十分的方便,这里我们将通过一系列的例子来进行说明。

    1 单独使用include

  在介绍这个方法之前,我来先贴出实体之间的关联关系,假设这里有三个相互关联的实体vehiclewarranty、warrantywarninglevel、vehiclewarrantyrepairhistory这三个实体后面两个都是第一个的子级并且并且vehiclewarranty、warrantywarninglevel之间的关系是1对1的关系,vehiclewarranty和vehiclewarrantyrepairhistory之间是1:n的关系,即1对多的关系,我们这里贴出具体的model,从而方便后面分析具体的代码。

  这里我们贴出第一个简单的查询示例,通过include方法来一下子查询出关联的三包预警等级这个实体,在我们的例子中我们返回的结果是带分页的,而且会根据前端传递的dto来进行过滤,这里我们来看这段代码怎么实体。

  在这里我们看到了通过一个include就能够查询出关联的实体,为什么能够实现,那是因为在vehiclewarranty实体中存在warrantywarninglevel实体的外键,并且这里还增加了外键关联的实体,这样才能够正确使用include方法,并且这个include方法只能够以实体作为参数,不能以外键作为参数,到了这里我想提出一个问题,这里最终生成的sql(sqlserver数据库)是left join 还是inner join呢?在看完后面的分析之前需要思考一下。

  这里我们看到生成的sql语句是left join ,那么这里为什么不是inner join呢?这里先给你看具体的答案吧?这里你看懂了吗?问题就处在我这里建立的外键是可为空的 public guid? warninglevelid { get; set; }、如果是不可为空的外键那么生成的sql就是inner join这个你可以亲自尝试。另外有一个需要提醒的就是,如果你像上面的实体中建立了vehiclewarranty、warrantywarningleve之间的关系的话,迁移到数据库会默认生成外键约束,这个在使用的时候需要特别注意,但是如果你只是添加了外键而没有添加对应的外键同名的实体是不会生成外键约束关系的,这个暂时不理解里面的实现机制。

  2 主清单使用include

  刚才介绍的是1对1的关联关系,那么像vehiclewarranty、vehiclewarrantyrepairhistory之间有明显的主清单关系,即一个vehiclewarranty对应多个vehiclewarrantyrepairhistory的时候使用include方法会生成什么样的sql语句呢?这里我也贴出代码,然后再来分析生成的sql语句。

  这里使用了两个include方法,那么efcore会怎么生成这个sql呢?通过查询最终的sql我们发现efcore在处理这类问题的时候是分开进行查询,然后再合并到查询的实体中去的,所以在这个查询的过程中生成的sql如下:

  这个在查询的过程中会分作几个sql查询并且会将前面查询的结果作为后面查询的部分条件来进行了,待整个查询完毕后再在内存中将这些结果组合到一个query对象中。

  3 theninclude用法

  上面的介绍完了之后,你应该能够明白这个include的具体含义和用法了,接着上面的例子,如果warrantywarninglevel里面还有通过外键id去关联别的实体,这个时候theninclude就派上了用场了,理论上只要彼此之间建立了这种外键关系就可以一直theninclude下去,但是一般情况下不会用到这么复杂的情况,当然这里面每一个include也都是作为一个单独的查询来进行的,这个也可以找具体的例子进行试验,这里也贴出一个具体的例子吧。

  最后还要介绍一种极特殊的情况,由于theninclude方法只能一层层向下进行,如果我想对同一个实体里面的两个关联实体做theninclude操作这个怎么处理,这里就直接给出代码吧。

  这里需要include同一个实体两次,然后分别调用theninclude方法,这个属于比较特殊的情况,在使用的时候需要注意。

  温馨提示:

  这里读者在看代码的时候可能不太理解类似这种 _repaircontractrepository的具体由来,这里贴出一份完整的代码。

  4 includefilter用法

  在有些场景中我们可能需要带出清单的时候并且过滤清单,这个功能算是对include方法的一个提升,可以将两个操作合并到一起来进行,这个在使用的时候需要注意 这个并不是asp.net core自带的功能,这个需要通过引入包 z.entityframework.plus.efcore.dll的包来实现的,如果你们的系统中使用的是abp作为项目主框架,那么你只需要引用 abp.entityframeworkcore.efplus这个包就可以了,因为这个包中就包含和z.entityframework相关的子包,这个在使用的时候需要注意。

   下面我们来看一看我们的代码中是怎么使用的。

  这个提供了一种新的清单过滤方式,不仅提高了效率而且使代码更加优化简练。

  5 特殊情况

  这里还介绍一种不通过include方法来获取清单中的方式,就像下面这种写法,company对象和orderingcalendars之间建立了一对多的导航属性,我们在使用 company.orderingcalendars之前先将内部的清查查询出来(不需要定义变量接收,使用_即可),这样也是能通过导航属性自动映射到company的orderingcalendars中去的,这个在使用的时候需要特别注意,查询的时候要提前tolist,将数据查询到内存里面

以上就是详解efcore中的导航属性的详细内容,更多关于efcore 导航属性的资料请关注其它相关文章!

《详解EFCore中的导航属性.doc》

下载本文的Word格式文档,以方便收藏与打印。