摘要: 上次为大家介绍EF Power Tool之后,不少朋友在使用的时候碰到了一些问题曾像我提问。我自己以及同事在使用这个工具时,其实也碰到了一些问题。今天我将和大家一起分享其中2个问题以及相应的原因。 1. EF Power Tool帮助我们生成Code First POCO class时为何只生成了部分代码,甚至所使用的程序集都没有导入? 在输入了相应的数据库Named Instance和登录信息后...阅读全文
posted @ 2011-06-13 17:21 LingzhiSun 阅读(3088) 评论(26) 编辑

好像蛮长时间没有新文章带给大家了。前几天出差再加上忙着公司里的活儿,几乎都没时间上博客园了。今天正好有些时间,为大家简单介绍EF产品组新发布的一个牛逼的小工具——EF
Power Tool(翻译的话,好像就是牛逼工具哦?)
下次会为大家深入解析这个小工具。  最先看到这个工具是在EF产品组最新的博客文章上,http://blogs.msdn.com/b/adonet/archive/2011/05/18/ef-power-tools-ctp1-released.aspx。粗略读了下,感觉很酷,马上下载下来试了试,果然很酷,http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d/

大致来说,这个工具有这样几个功能:

1) 按照现有数据库结构,生成Code First POCO class、DbContext class和相应的mapping class。

2) 以designer模式或XML模式查看POCO class对应的Entity Data Model (edmx) 。

3) 查看Entity Data Model所对应的DDL。

4) 生成EF Generated View提高EF性能。

 

一起来体验下。当然请先下载安装这个小工具,安装前必须先安装EF4.1

首先在数据库端创建两个表Parent和Child,存在一对多的关系。

 

创建一个C#项目,并右击项目名。在弹出的菜单中选择Entity Framework –> Reverse Engineer Code
First。

 

接着需要选择相应的数据库连接:

 

接着,神奇的一幕发生了。小工具帮助我们生成了不少class:

 

相应的POCO class, DbContext class和mapping fluent API都自动生成了,真是太轻松了。这样大大方便了我们学习EF
4.1的相关fluent API。

 public class Parent
{
public Parent()
{
this.Children = new List<Child>();
}
public int ParentID { get; set; }
public string Name { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
 
 public class EFToolContext : DbContext
{
static EFToolContext()
{
Database.SetInitializer<EFToolContext>(null);
}
public DbSet<Child> Children { get; set; }
public DbSet<Parent> Parents { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Configurations.Add(new ChildMap());
modelBuilder.Configurations.Add(new ParentMap());
}
}

 public class ParentMap : EntityTypeConfiguration<Parent>
{
public ParentMap()
{
// Primary Key
this.HasKey(t => t.ParentID);
// Properties
this.Property(t => t.ParentID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(t => t.Name)
.IsRequired()
.HasMaxLength(50);
// Table & Column Mappings
this.ToTable("Parent");
this.Property(t => t.ParentID).HasColumnName("ParentID");
this.Property(t => t.Name).HasColumnName("Name");
}
}

拥有了这些class之后,我们还可以通过小工具来查看相应的Entity Data Model以及对应的DDL。更牛的是,小工具还可以为我们生产EF
Generated View的代码,以提高我们使用EF和Code First时的性能。

 

值得一提的是,这里的Entity Data Model,Entity Data Model XML和Entity Data Model
DDL都是只读的,它们被生成在C:\Users\[username]\AppData\Local\Temp\文件夹下。

 

在选择Optimize Entity Data Model之后,小工具会为你的项目增加一个.View.cs文件,期中就包括了Generated
Views的代码。有关Generated View的更详细信息,请参见:http://msdn.microsoft.com/en-us/library/bb896240.aspx

是不是觉得这个工具很酷呢?赶紧下载吧! http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d/

 

PS1: 顺便为大家奉上新鲜出炉的微软一站式示例代码库中文宣传视频,绝对给力,我翻译的字幕哟

 


PS2: 为大家带来另一个超级酷的小工具:MSDN论坛桌面小工具,绝对给力!欢迎使用!(我也出了不少力啊


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

 

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

posted @ 2011-05-24 17:24 LingzhiSun 阅读(8728) 评论(38) 编辑

最近挺忙的,只能为大家带来一些使用EF的小技巧。有关EF4.1的使用与探索将在之后一段时间为大家奉上。今天为大家带来如何得到EF查询所生成的SQL。


在EF 4和EF 3.5 SP1中,我们可以使用ToTraceString()方法得到EF查询所生成的SQL。 

using (var context = new TestDBEntities())
{
    var query 
= from p in context.Parents
                
where p.Name == "Lingzhi"
                select p;

    ObjectQuery
<Parent> parents = query as ObjectQuery<Parent>;
    
if (parents != null)
    {
        
string sql = parents.ToTraceString();
    }
}

这里所生成的SQL为:

SELECT 
[Extent1].[ParentID] AS [ParentID]
[Extent1].[Name] AS [Name]
FROM [dbo].[Parent] AS [Extent1]
WHERE N'Lingzhi'=[Extent1].[Name]


在EF 4.1中,我们可以直接调用DbQuery<>的ToString()方法得到所生成的SQL。

using (var context = new MyDbContext())
{
    var people 
= from p in context.People
                 
where p.PersonID > 100
                 select p;

    
string sql = people.ToString();
}

所生成的SQL是:

SELECT 
[Extent1].[PersonID] AS [PersonID]
[Extent1].[Name] AS [Name]
FROM [dbo].[People] AS [Extent1]
WHERE [Extent1].[PersonID] > 100

 

大家应该已经猜到,这里的ToString()方法其实也就是调用了ObjectQuery<>的ToTraceString()方法。DbQuery<>.ToString() ==> System.Data.Entity.Internal.Linq.InternalQuery<>.ToString()方法,此方法在.NET Reflector得到的实现是这样的:

public override string ToString()
{
    
return this._objectQuery.ToTraceString();
}

 

以上讨论的方法都只能得到普通Select查询所生成的SQL,像其他Loading啊,更新啊,删除啊,添加等所生成的SQL并不能得到。EF并不像LINQ to SQL有DataContext.Log可以得到所有被执行的SQL命令。要实现这样的功能,需要自己拓展一下EF的data provider,比如这个例子:http://code.msdn.microsoft.com/EFProviderWrappers-c0b88f32。(可能的话,以后会为大家详细介绍下这个很酷的provider)

 

当然我们也可以使用Visual Studio 2010 Ultimate所带的IntelliTrace功能或者SQL Server Profiler来得到EF所生成的SQL。 不过这两种方法只针对SQL Server和对应的T-SQL。

 

PS1:这里为大家带来一个好消息:微软一站式实例代码库(Microsoft All-In-One Code Framework)即日起正式迁移至MSDN代码库了,新的平台会帮您更轻松地解决开发难题、节省更多时间、获得更友好的用户体验。本人作为这个项目的元老,见到我们已拥有600多个经典的代码实例,甚感欣慰啊!  更详细信息,请看http://msdn.microsoft.com/zh-cn/hh124104.aspx?ocid=ban-f-cn-loc-OC201104-MSDN

最新的代码浏览器也发布啦!为大家带来了更多很cool的功能,比如1)代码按需下载 2)实例集中化管理  3)自动更新

http://blog.csdn.net/MSCodeSample/archive/2011/04/18/6331382.aspx 

之后我将尽力为大家带来更多有关EF的代码实例以及相关的介绍!



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


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

 

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

posted @ 2011-05-05 09:07 LingzhiSun 阅读(3176) 评论(17) 编辑

有时我们的实体只需要显示,无需更新,所以为了提高性能,我们不需要实体被EF context追踪。此时可以使用NoTracking的查询来得到实体,这样实体的状态会是Detached状态。

 

在EF3.5 SP1和EF 4中,我们可以这样来进行NoTracking查询:

using (var context = new MyObjectContext())
{
    context.People.MergeOption 
= System.Data.Objects.MergeOption.NoTracking;
    var list 
= context.People.Where(p => PersonID > 100).ToList();
}

或使用ExecuteStoreQuery API来直接调用SQL命令来得到实体:

using (var context = new MyObjectContext())
{
    var query 
= context.ExecuteStoreQuery<Parent>("SELECT * FROM Parent WHERE Parent.ParentID > @ID""TestDBEntities.Parents"System.Data.Objects.MergeOption.NoTrackingnew SqlParameter("@ID"100));
}

或使用Load方法得到相关实体:

using (var context = new MyObjectContext())
{
    context.ContextOptions.LazyLoadingEnabled 
= false;
    var person 
= context.People.First();
    person.Courses.Load(System.Data.Objects.MergeOption.NoTracking);
}


在EF 4.1中,我们可以使用新增的AsNoTracking方法:

using (var context = new MyDbContext())
{
     var people 
= context.People.Where(p => p.PersonID > 100).AsNoTracking().ToList();
}

 

这里的AsNoTracking方法内部调用了过去的ObjectQuery.MergeOption来实现NoTracking查询。此方法(DbHelpers.CreateNoTrackingQuery)是AsNoTracking方法的核心:

public static IQueryable CreateNoTrackingQuery(ObjectQuery query)
{
    IQueryable queryable 
= query;
    ObjectQuery query2 
= (ObjectQuery) queryable.Provider.CreateQuery(queryable.Expression);
    query2.MergeOption 
= MergeOption.NoTracking;
    
return query2;
}

 

再为大家介绍NoTracking得到的Detached实体的一个小问题。由NoTracking查询得到的实体和我们直接调用Detach方法得到的实体不同。前者内部会仍然保留一个对当前context的引用,以便在调用Load方法可以explicitly load相关的实体。而后者则完全脱离了相应的context,所以属于真正的Detached状态。细心的读者可能会觉得NoTracking得到的Detached实体会导致context一直被引用,从而不能及时被垃圾处理(GC)。确实,这个被产品组证实是by design的,如果context不被引用,则explicit load则无法被支持。有关这个问题的更详细信息,请参看:

http://connect.microsoft.com/VisualStudio/feedback/details/507482/entity-framework-query-with-mergeoption-notracking-result-memory-leak

http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/906c0cad-840b-4eb8-ba11-5348d407df73 (我前年处理的一个MSDN帖子)

 

 

PS1:这里为大家带来一个好消息:微软一站式实例代码库(Microsoft All-In-One Code Framework)即日起正式迁移至MSDN代码库了,新的平台会帮您更轻松地解决开发难题、节省更多时间、获得更友好的用户体验。本人作为这个项目的元老,见到我们已拥有600多个经典的代码实例,甚感欣慰啊!  更详细信息,请看http://msdn.microsoft.com/zh-cn/hh124104.aspx?ocid=ban-f-cn-loc-OC201104-MSDN

最新的代码浏览器也发布啦!为大家带来了更多很cool的功能,比如1)代码按需下载 2)实例集中化管理  3)自动更新

http://blog.csdn.net/MSCodeSample/archive/2011/04/18/6331382.aspx 

之后我将尽力为大家带来更多有关EF的代码实例以及相关的介绍!



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


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

 

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

posted @ 2011-04-27 09:16 LingzhiSun 阅读(2374) 评论(7) 编辑

在使用EF的集合类型的Navigation Property时,我时常需要只导入符合特定条件的实体对象,例如:Blog类和Post类存在一对多关系,即一个博客可以拥有多篇博文。现在我们想获得博客以及其相关博文中在今年1月1日之后发表的所有博文,可是之前EF版本所提供的Lazy LoadingExplicitly LoadingEagerly Loading都不支持在Navigation Property上增加一个过滤条件。有关三种Loading的详细信息,不在本文过多介绍,请见MSDN文档:http://msdn.microsoft.com/en-us/library/bb896272.aspx,或者参看我以前写过的一篇英文MSDN博客:http://blogs.msdn.com/b/msdnforum/archive/2010/07/12/community-goodies-lazy-loading-in-entity-framework-4.aspx。之后也会为大家带来有关Loading的文章。

 

过去我们可以用以下两种方法来实现这一目的:

1)  利用匿名类,并且将过滤条件嵌入到返回的匿名类中:

using (var context = new MyObjectContext))
{
    var query 
= (from b in context.Blogs
                 
where b.Tags.Contains("EF")
                 select 
new 
                 {
                     Blog 
= b,
                     Posts 
= b.Posts.Where(p => p.CreationTime >= new DateTime(201111))
                 }).ToList();

} 

不过,此方法的缺点显而易见, 我们必须使用匿名类来包装实体对象,在数据绑定时会有挺多问题。

 

2)   使用多个query,让EF的跟踪机制帮助我们建立对象之间的联系。(EF4和EF4.1中,我们需要关闭Lazy Loading)

using (var context = new MyObjectContext))
{
    
// For EF4
    
// context.ContextOptions.LazyLoadingEnabled = false;
    // For EF4.1
    // context.Configuration.LazyLoadingEnabled = false;
    var blogs = (from b in context.Blogs
                 
where b.Tags.Contains("EF")
                 select b).ToList();
    
    var posts 
= (from p in context.Posts
                 
where p.Blog.Tags.Contains("EF")
                 
&& p.CreationTime >= new DateTime(201111)
                 select p).ToList();
}

在两个query执行之后,EF的ObjectStateManager会自动建立Blog和Post之间的关系,如果我们访问blogs.First().Posts属性,将得到的都是今年1月1日之后创建的博文。

 

当然我想这两个方法在EF4.1中同样能成功。幸运的是,EF4.1提供了新的功能使我们可以在使用Explicitly Loading时添加过滤条件。

using (var context = new MyDbContext())
{
   var blog 
= context.Blogs.Where(b => b.Tags.Contains("EF")).First();

   context.Entry(blog).
Collection(b => b.Posts)
          .Query()
          .Where(p 
=> p.CreationTime >= new DateTime(201111))
          .Load();

   
// 或者使用String类型来标记Blog与Post的关系
   context.Entry(blog).Collection("Posts")
          .Query().Cast
<Post>()
          .Where(p 
=> p.CreationTime >= new DateTime(201111))
          .Load();
}

Collection()方法在这里返回DbCollectionEntry,Query()方法返回对应的IQueryable<T>对象。熟悉LINQ的同志们一定知道,得到IQueryable<T>了的话,一切好说,哈哈。EF4.1中,System.Data.Entity命名空间下的DbExtensions类中定义了不少LINQ的扩展方法,其中一个就是Load方法。用Reflector看了下Load方法的实现,其实就是调用IEnumerator.MoveNext遍历一遍集合:

using (IEnumerator enumerator = source.GetEnumerator())
{
    
while (enumerator.MoveNext())
    {
    }
}
值得注意的是:在EF4.1中使用这一功能最好也关闭Lazy Loading,否则一旦对应的集合类型的Navigation Property被访问的话,所有对应的实体都将被导入。

 

当然这里如果我们不想导入这些相关的实体对象,也可以使用Count()方法得到符合条件对象的数量。这样我们得到的是实体的数量,而没有一个对应实体会被导入。

using (var context = new MyDbContext())
{
   var blog 
= context.Blogs.Where(b => b.Tags.Contains("EF")).First();

   context.Entry(blog).Collection(b 
=> b.Posts)
          .Query()
          .Count();
}


一口气搞定这篇,希望对大家学习EF有所帮助吧! 

 

 

PS1:这里为大家带来一个好消息:微软一站式实例代码库(Microsoft All-In-One Code Framework)即日起正式迁移至MSDN代码库了,新的平台会帮您更轻松地解决开发难题、节省更多时间、获得更友好的用户体验。本人作为这个项目的元老,见到我们已拥有600多个经典的代码实例,甚感欣慰啊!  更详细信息,请看http://msdn.microsoft.com/zh-cn/hh124104.aspx?ocid=ban-f-cn-loc-OC201104-MSDN

最新的代码浏览器也发布啦!为大家带来了更多很cool的功能,比如1)代码按需下载 2)实例集中化管理  3)自动更新

http://blog.csdn.net/MSCodeSample/archive/2011/04/18/6331382.aspx 

之后我将尽力为大家带来更多有关EF的代码实例以及相关的介绍!



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


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


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

posted @ 2011-04-19 09:11 LingzhiSun 阅读(2750) 评论(22) 编辑
摘要: 相信不少使用EF的同志们已经知道如何在EF中运行SQL命令了。我在这里简单总结下,希望对大家学习EF有所帮助!在EF第一个版本(.NET 3.5 SP1)中,我们只能通过将ObjectContext.Connection转换为EntityConnection,再把EntityConnection.StoreConnection转换为SqlConnection。有了这个SqlConnection,我...阅读全文
posted @ 2011-04-15 11:09 LingzhiSun 阅读(3805) 评论(15) 编辑
摘要: 之前的两篇有关EF4.1的文章反响不错,感谢大家的支持!想体验EF4.1的新功能?RTW版本已经发布啦,http://www.microsoft.com/downloads/en/details.aspx?FamilyID=b41c728e-9b4f-4331-a1a8-537d16c6acdf&displaylang=en Entity Framework 4.1 DbContext使用记之一...阅读全文
posted @ 2011-04-13 09:32 LingzhiSun 阅读(7874) 评论(41) 编辑
摘要: DbContext及其相关的API是EF4.1中一大新特性。简单说,DbContext就是之前EF的核心类ObjectContext的抽象封装。如果用.NET Reflector看一下DbContext的内部实现,不难发现其内部有一私有成员_internalContext,它属于InternalContext这一Internal的类。DbContext内部的许多函数就是通过InternalContext.ObjectContext属性来得到其内部封装的ObjectContext类并调用其方法的。由于_internalContext是私有成员,要得到它的值需动用反射,好像太劳师动众了。今天为大家阅读全文
posted @ 2011-03-30 09:10 LingzhiSun 阅读(3325) 评论(10) 编辑
摘要: 说好为大家带来一系列的文章,现在就写第二篇。开始之前,再啰嗦两句,EF4.1 RTW版本已经发布:http://www.microsoft.com/downloads/en/details.aspx?FamilyID=b41c728e-9b4f-4331-a1a8-537d16c6acdf&displaylang=en。第一篇有关DbSet.Find的文章,请看:http://www.cnblog...阅读全文
posted @ 2011-03-25 09:44 LingzhiSun 阅读(6143) 评论(24) 编辑
摘要: 随着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有一些初级...阅读全文
posted @ 2011-03-22 17:49 LingzhiSun 阅读(7587) 评论(23) 编辑