Entity Framework 4.1 DbContext使用记之一——如何查找实体? DbSet.Find函数的使用与实现...

随着 EF4.1 RC上周的 发布MSDN EF论坛的帖子也越来越多。相信大家会对EF4.1的一些新功能感兴趣。之后会为大家带来一系列的文章,与大家分享下我学习EF4.1的一些经验与感想。

顺便提一句,EF4.1的MSDN文档已经发布, http://msdn.microsoft.com/en-us/library/gg696172(v=VS.103).aspx。这一系列文章,可能需要您对EF有一些初级的认识。头一次写这样介绍性的文章,大家多提意见!

[4.13添加]EF4.1 RTW 版本也发布啦,http://www.microsoft.com/downloads/en/details.aspx?FamilyID=b41c728e-9b4f-4331-a1a8-537d16c6acdf&displaylang=en

 

第一篇为大家带来新的API,DbSet<>.Find()

 

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

var people  =  from p  in  context.People
             
where  p.Name.StartsWith( " M " )
             select u;

var people = context.People.FirstOrDefault(p => p.Name == "Michael");  

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

 

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

 

比如我们查找主键PersonID为1的Person实体:

var person = context.People.Find(1);

 

也可用于联合主键(比如查找主键PersonID=1, PersonName="Michael"的实体):

 

var person  =  context.People.Find( 1 " Michael " );

 

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

 

和之前直接用Where或First的调用不同,Find函数对于刚刚新增的实体也能找到:

 

using  (var context  =   new  MyContext())
{
    context.People.Add(
new  People { PersonID  =   100  });
    var newPerson 
=  context.People.Find( 100 );
}

 

 

了解了Find函数的基本用法后,让我们来看看Find函数是如何实现的。这里我们借用了.NET Reflector来查看EF4.1的最重要的程序集EntityFramework.dll。

Find函数首先调用了EF的内部实现:

 

public  TEntity Find( params   object [] keyValues)
{
    
this .InternalContext.DetectChanges( false );
    WrappedEntityKey key 
=   new  WrappedEntityKey( this .EntitySet,  this .EntitySetName, keyValues,  " keyValues " );
    
object  obj1  =   this .FindInStateManager(key);
    
if  (obj1  !=   null )
    {
        
goto  Label_003E;
    }
    
object  obj2  =   this .FindInStore(key,  " keyValues " );
    
if  ((obj2  !=   null &&   ! (obj2  is  TEntity))
    {
        
throw  Error.DbSet_WrongEntityTypeFound(obj2.GetType().Name,  typeof (TEntity).Name);
    }
    
return  (TEntity) obj2;
}

 

这里,EF首先调用了DetectChanges()来同步内部ObjectContext跟踪的对象的状态。WrappedEntityKey则对过去的EntityKey做了一个包装,每个主键对应于一个KeyValuePair。将Find函数的输入值一一包装成KeyValuePair,并最终生成EntityKey对象。

 

之后,Find函数调用了FindInStateManager函数。顾名思义,EF首先在内部缓存中查找对应实体。对于状态是Unchanged、Modified以及Deleted的实体,FindInStateManager直接使用了过去ObjectContext.ObjectStateManager.TryGetObjectStateEntry方法,并且直接将EntityKey传给该方法。对于状态是Added的新增实体,这里需要做的处理稍微复杂一些。EF先调用了ObjectStateManager.GetObjectStateEntries(EntityState.Added)方法得到所有状态是Added的Entry。然后依次比较主键的值(之前得到的KeyValuePair)以判定是否为所要的实体。在得到Added状态的实体的值时,EF也使用了ObjectStateEntry.CurrentValues

 

如果在内部缓存中找不到相应的实体,Find函数会调用FindInStore函数来对数据库进行查找。FindInStore函数内部使用了Entity SQL的查询,以这样一个Entity SQL命令为基础:SELECT VALUE X FROM {0} AS X WHERE。再将对应的主键名字拼接到这个命令中。主键值则以ObjectParameter的形式传递。最后FindInStore调用ObjectContext.CreateQuery<>(...).SingleOrDefault()函数来执行Entity SQL查询。由于最后使用了SingleOrDefault,如果数据库中也没有对应的实体存在,Find函数会返回NULL。

 

终于一口气写完,希望对您学习EF有所帮助吧!


系列博文之二: Entity Framework 4.1 DbContext使用记之二——DbSet.Local属性的使用与实现

系列博文之三: Entity Framework 4.1 DbContext使用记之三——如何玩转实体的属性值?

 

PS:同事开发了一个很cool的MSDN论坛桌面小工具,绝对给力!欢迎使用!(我也出了不少力啊


也欢迎到MSDN中文论坛ADO.NET与LINQ论坛来提问EF的问题啊,可以试试直接报我的名字Michael Sun,哈哈! 

 

如需转发请注明原文出处,谢谢: http://www.cnblogs.com/LingzhiSun/archive/2011/03/22/EF41_Find.html

转载于:https://www.cnblogs.com/LingzhiSun/archive/2011/03/22/EF41_Find.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 System.Data.Entity DbContext 创建 SQLite 数据库和数据表,您需要安装两个 NuGet 包: 1. System.Data.SQLite.Core:提供 SQLite 数据库的核心功能。 2. System.Data.SQLite.EF6:提供 Entity Framework 6 的 SQLite 数据提供程序。 安装 NuGet 包后,您可以使用以下步骤创建 SQLite 数据库和数据表: 1. 在应用程序中创建一个派生自 DbContext 的类。例如: ```csharp using System.Data.Entity; public class MyDbContext : DbContext { public MyDbContext() : base("MyConnectionString") { } public DbSet<MyEntity> MyEntities { get; set; } } ``` 2. 在应用程序的配置文件(如 app.config 或 web.config)中添加连接字符串。例如: ```xml <connectionStrings> <add name="MyConnectionString" connectionString="Data Source=MyDatabase.sqlite" providerName="System.Data.SQLite.EF6" /> </connectionStrings> ``` 3. 在应用程序启动时,将数据库初始化为最新模型。例如: ```csharp Database.SetInitializer(new CreateDatabaseIfNotExists<MyDbContext>()); ``` 4. 在 DbContext 中定义实体类。例如: ```csharp public class MyEntity { public int Id { get; set; } public string Name { get; set; } } ``` 5. 在 DbContext使用 DbSet 属性定义数据表。例如: ```csharp public DbSet<MyEntity> MyEntities { get; set; } ``` 6. 使用 DbContext.SaveChanges() 方法保存更改。例如: ```csharp using (var context = new MyDbContext()) { var entity = new MyEntity { Name = "Test" }; context.MyEntities.Add(entity); context.SaveChanges(); } ``` 这样就可以使用 System.Data.Entity DbContext 创建 SQLite 数据库和数据表了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值