关于Entity Framework自动关联查询与自动关联更新导航属性对应的实体注意事项说明...
一、首先了解下Entity Framework 自动关联查询:
Entity Framework 自动关联查询,有三种方法:Lazy Loading(延迟加载),Eager Loading(预先加载),Explicit Loading(显式加载),其中Lazy Loading和Explicit Loading都是延迟加载。
(注:由于Entity Framework版本的不同,以及采用不同的模式(DB First,Model First,Code First)来构建的Entity,最终导致可能自动关联查询的方法也有所不同,本文中的示例代码均以Entity Framework 6.0,且采用Code First模式来构建的Entity为基础)
一、Lazy Loading(延迟加载):这是默认情况(默认实体上下文对象的属性:Configuration.LazyLoadingEnabled=true,若该属性设为false则无效),若实体类型包含其它实体类型(POCO类)的属性(也可称为导航属性),且同时满足如下条件即可实列延迟加载,
1.该属性的类型必需为public且不能为Sealed;
2.属性标记为Virtual
作用:在您访问导航属性时,会从数据源自动加载相关实体,若实体尚未在 实体上下文对象中,则您访问的每个导航属性都会导致针对数据源执行一个单独的查询。
示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
[Table( "User" ,Schema= "dbo" )]
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name = "用户ID" )]
public int ID { get ; set ; }
[Required]
[MinLength(6)]
[MaxLength(15)]
[Unique( "User" , "UserName" )]
[Display(Name = "用户名" )]
public string UserName { get ; set ; }
[Required]
[Display(Name = "密码" )]
public string Password { get ; set ; }
[Required]
[Display(Name = "用户类型" )]
public int UserTypeID { get ; set ; }
[ForeignKey( "UserTypeID" )]
public virtual UserType UserType { get ; set ; } //此属性在查询User时,会自动依据UserTypeID 关联查旬UserType ,并将结果赋值给UserType 属性
}
|
二、Eager Loading(预先加载):在LazyLoadingEnabled设为false或导航属性没有使用Virtual的情况下,使用IQueryable的扩展方法Include指定预先加载关联的实体。
作用:Include方法中的查询路径指定将哪些相关实体作为初始查询的一部分返回,当在查询语句中定义了Include查询路径,查询时仅需对数据库请求一次,即可在单个结果集中返回查询路径所定义的所有实体。
示例代码如下:
1
2
3
4
5
|
var entitiesContext= new TEMSContext();
entitiesContext.Configuration.LazyLoadingEnabled= false ;
var users = entitiesContext.Users.Include( "UserType" );
//var users = entitiesContext.Set<User>().Include("UserType");与上面语句相同
Assert.AreNotEqual( null , users.First().UserType);
|
三、Explicit Loading(显式加载):在LazyLoadingEnabled设为false或导航属性没有使用Virtual的情况下,使用DbEntityEntry.Reference方法来显式加载指定导航属性的单个值,DbEntityEntry.Collection方法来显式加载指定导航属性的值集合,若采用DB First时,可使用ObjectContext.LoadProperty方法来显式加载指定导航属性。
作用:查询时并不会从数据库查询并加载导航属性的值,仅当使用Reference或Collection方法来指定导航属性,并调用Load方法时或调用ObjectContext.LoadProperty,才会从数据库查询数据并赋值给指定的导航属性,若查询的结果集较多时,可能会出现多次往返查询数据。
示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//这是Code First模式下显式加载数据
var entitiesContext = new TEMSContext();
entitiesContext.Configuration.LazyLoadingEnabled = false ;
var user = entitiesContext.Users.First();
var u = entitiesContext.Entry(user);
u.Reference(t => t.UserType).Load();
Assert.AreNotEqual( null , user.UserType);
//这是DB First模式下显示式加载数据
var db = new aTestEntities();
db.ContextOptions.LazyLoadingEnabled = false ;
var comp = db.Companies.First();
db.LoadProperty(comp, t => t.Departments);
Assert.AreNotEqual(0, comp.Departments.Count);
|
二、自动关联更新导航属性对应的实体注意事项说明
若开启了Lazy Loading(延迟加载)模式,即满足上面第一种关联查询条件时,在执行实体新增的时,需注意:如果直接赋值给导航属性,则当提交到数据库时,会自动关联新增导航属性对应的表记录,不论你是否在实体中有指定导航属性对应的外键属性的值,仍会以关联新增导航属性对应的表记录后更新该外键属性的值,可能表达有点不清楚,请看下面的示例:
1
2
3
4
|
var entitiesContext = new TEMSContext();
User user = new User() {UserName= "testuser" ,RealName= "测试账号" ,CompanyID = 1, Company = UserBusiness.CurrentUser.Company };
entitiesContext.Users.Add(user);
entitiesContext.SaveChanges();
|
以上代码中,CompanyID为导航属性Company的外键属性,我这里直接将两个属性都赋值了,Company的ID也是1(Company表中存在ID为1的记录),UserBusiness.CurrentUser为我系统当前登录的用户,按理讲,执行新增后,应该只会在User表中新增一条记录,而实际却是先在Company表中新增一条记录(忽略指定的主键,即:ID=1),并将返回的新ID赋值给CompanyID(比如为2),然后再在User表中新增一条记录,最终形成User.CompanyID=2,而不是1,这个问题也是困扰我好几天了,也没有找到根本原因,目前的解决办法是只赋值外键属性CompanyID,而导航属性Company则不赋值,这样在保存时就不会出错了。如果大家知道原因还请告之,非常感谢!
本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/4514230.html ,如需转载请自行联系原作者
关于Entity Framework自动关联查询与自动关联更新导航属性对应的实体注意事项说明...相关推荐
- java多对多关联数据操作,hibernate实施多对多关联查询时,关联表数据被删除
hibernate执行多对多关联查询时,关联表数据被删除 本帖最后由 binbb521 于 2012-12-04 11:48:29 编辑 S2SH框架开发的网站,执行两个多对多关系的表查询时,关联两个 ...
- jpa多表关联查询_JPA【关联查询篇】
摘要:本文主要介绍JPA的多表关联查询(一对一.一对多.双向关联.多对一.多对多)以及N+1查询的优化. 1. JPA多表关联查询 多表关联查询就是实现使用一个实体类对象操作或者查询多个表的数据. 配 ...
- Entity Framework Core Like 查询揭秘
在Entity Framework Core 2.0中增加一个很酷的功能:EF.Functions.Like(),最终解析为SQL中的Like语句,以便于在 LINQ 查询中直接调用. 不过Entit ...
- Linq to sql 结合Entity Framework 的连接查询总结
最近在做项目使用linq结合EntityFramework来处理数据库的操作.想来也用了快一年了,发现有些使用技巧是需要注意下,特做下总结,希望对刚入门的朋友们有所帮助.刚开始用的时候各总循环查询子查 ...
- MyBatis框架学习 DAY_03:如何解决无法封装问题 / 一对一关联查询 / 一对多关联查询
1. 通过查询时自定义别名的方式解决名称不一致而导致的无法封装数据的问题 假设,向用户组数据表(t_group)表中插入一些测试数据: INSERT INTO t_group (name) VALUE ...
- 14、mybatis多表关联查询 association定义关联对象封装规则及懒加载
文章目录 1.使用association单步查询 1).EmployeeMapper 2).EmployeeMapper.xml 3).Test 2.使用association进行分步查询 4).De ...
- Django学习笔记(3):使用模型类进行查询(查询函数、F对象、Q对象、聚合函数、查询集、模型类关系、关联查询、自关联、管理器)
文章目录 1.查询函数 2.F对象 3.Q对象 4.聚合函数 5.Count函数 6.查询集 查询集的特性 对查询集进行切片 判断一个查询集中是否有数据 7.模型类之间的关系 一对多关系 多对多关系 ...
- Entity Framework 4.1 DbContext使用记之二——如何玩转本地实体? DbSet.Local属性的使用与实现...
说好为大家带来一系列的文章,现在就写第二篇.开始之前,再啰嗦两句,EF4.1 RTW版本已经发布:http://www.microsoft.com/downloads/en/details.aspx? ...
- java mybtis关联查询,7.MyBatis 关联查询(一对一)
1 关联查询映射 1.1 分析数据模型 思路 :每张表记录的数据内容 每张表重要的字段(主键,外键,非空字段) 表与表之间的关系(外键关系) 表与表之间的业务关系(建立在某个业务意义基础上去分析) 如 ...
最新文章
- 论文:基于粒子群优化的测试数据生成及其实证分析-----生成过程以及实验(计算机研究与发展)
- oracle 更新丢失
- golang goroutine 协程同步 sync.WaitGroup 简介
- Delphi手动创建数据集
- C++ Qt学习笔记(4)绘图
- Jquery Ajax 异步设置Table中某列的值
- 利用ggseqlogo绘制seqlogo图
- api-ms-win-crt-runtime-l1-1-0.dll丢失问题
- java 发送邮件怎么抄送,Java实现邮件发送(二)
- Deep Glow for mac(AE高级辉光特效插件)
- VS2015社区版使用Visual Studio Installer打包
- 基于toolbox_calib工具箱的相机标定matlab仿真
- DAS、NAS、SAN简介以及区别
- 【Java】猜数字,程序随机分配给客户一个1-100之间的整数,用户在输入对话框中输入自己的猜测,程序返回提示信息,提示信息分别是:“猜大了”、“猜小了”和“猜对了”,用户可根据提示信息再次输入猜测
- java程序如何在手机运行_怎么在手机上运行手机JAVA程序
- 有没有什么好的可以做读书笔记的APP推荐?
- 华为手机鸿蒙系统官方下载入口,华为鸿蒙系统官方下载入口v.20
- 微信公众号怎么添加外链
- Mysqldump参数解析大全
- Springboot毕设项目教务管理系统l7srg(java+VUE+Mybatis+Maven+Mysql)
热门文章
- AI一分钟 | 贾跃亭这次真的没钱了,法拉第只够发到年底工资;自动驾驶风云:Uber竟被爆料收购窃取Waymo机密的公司
- 吊打 ThreadLocal!
- Linux内存、Swap、Cache、Buffer详细解析
- 阿里员工的Java问题排查工具单
- Springboot启动原理解析
- 机器学习中的L1与L2正则化图解!
- 两位MIT学霸,25岁退学,40岁完成800亿IPO!
- 最大民科组织被取缔,鸡蛋返生、推翻相对论、量子速读都是他们干的
- 如何在Colab上实现近200万图片的精准检索匹配?
- 详解计算机视觉中的特征点检测:Harris / SIFT / SURF / ORB