首页 技术 正文
技术 2022年11月14日
0 收藏 959 点赞 3,775 浏览 2425 个字

过去我们常常使用Where或First(FirstOrDefault)方法来查找对应的实体,比如:

  1. var query = context.CertInfoMakeDetails.ToList().Where(make => int.Parse(make.CertCode) >= startcode &&
  2. int.Parse(make.CertCode) <=
  3. (startcode + count – 1) &&
  4. make.ProductName == productName);
var query = context.CertInfoMakeDetails.ToList().Where(make => int.Parse(make.CertCode) >= startcode &&
int.Parse(make.CertCode) <=
(startcode + count - 1) &&
make.ProductName == productName);

这样做的缺点是:即使我们相应的实体已经被DbContext缓存,EF还是会去执行数据库访问,而数据库访问是被普遍认为比较耗费性能的。

从EF4.1开始,微软为我们提供了一个新的API:DbSet<>.Find(),它可以帮助我们通过主键来查找对应的实体。并且如果相应的实体已经被DbContext缓存,EF会在缓存中直接返回对应的实体,而不会执行数据库访问。

比如我们查找证书ID为”101″的实体:

  1. var query = context.CertInfoMakeDetails.Find(“101”);
var query = context.CertInfoMakeDetails.Find("101");

也可以使用联合主键(比如查找CertCode = “101”, ProductName = “ABC”)的实体:

  1. var query = context.CertInfoMakeDetails.Find(“101”, “ABC”);
var query = context.CertInfoMakeDetails.Find("101", "ABC");

注意:此处输入联合主键的次序需要按照我们定义改实体类时声明主键的次序。

和之前使用Where或First调用不同,Find也可以找到刚刚新增的实体:

  1. using (var context = new MyContext())
  2. {
  3. context.CertInfoMakeDetails.Add(new CertInfoMakeDetail {….});
  4. var newOne = context.Find(“Id”);
  5. }
using (var context = new MyContext())
{
context.CertInfoMakeDetails.Add(new CertInfoMakeDetail {....});
var newOne = context.Find(“Id”);
}

最后让我们来看看Find是如何实现的:

  1. public TEntity Find(params object[] keyValues)
  2. {
  3. this.InternalContext.ObjectContext.AsyncMonitor.EnsureNotEntered();
  4. this.InternalContext.DetectChanges(false);
  5. WrappedEntityKey key = new WrappedEntityKey(this.EntitySet, this.EntitySetName, keyValues, “keyValues”);
  6. object obj2 = this.FindInStateManager(key) ?? this.FindInStore(key, “keyValues”);
  7. if ((obj2 != null) && !(obj2 is TEntity))
  8. {
  9. throw System.Data.Entity.Resources.Error.DbSet_WrongEntityTypeFound(obj2.GetType().Name, typeof(TEntity).Name);
  10. }
  11. return (TEntity) obj2;
  12. }
public TEntity Find(params object[] keyValues)
{
this.InternalContext.ObjectContext.AsyncMonitor.EnsureNotEntered();
this.InternalContext.DetectChanges(false);
WrappedEntityKey key = new WrappedEntityKey(this.EntitySet, this.EntitySetName, keyValues, "keyValues");
object obj2 = this.FindInStateManager(key) ?? this.FindInStore(key, "keyValues");
if ((obj2 != null) && !(obj2 is TEntity))
{
throw System.Data.Entity.Resources.Error.DbSet_WrongEntityTypeFound(obj2.GetType().Name, typeof(TEntity).Name);
}
return (TEntity) obj2;
}

首先,EF调用了EnsureNotEntered() 方法来检查内部ObjectContext的状态,如果这个实例当前获得了一个排它锁,那么就抛出异常。之后调用DetectChanges 方法来同步了对象状态。WrappedEntityKey 主要用来将Find函数的参数包装成一个KeyValuePair。

之后,Find 方法首先调用 FindInStateManager 方法在缓存中进行查找,如果找不到对应的实体,那么就调用 FindInStore 在对数据库进行查找,如果仍然找不到,就抛出异常,否则返回对应实体。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,961
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,485
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,330
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,113
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,746
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,780