好像蛮长时间没有新文章带给大家了。前几天出差再加上忙着公司里的活儿,几乎都没时间上博客园了。今天正好有些时间,为大家简单介绍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
最近挺忙的,只能为大家带来一些使用EF的小技巧。有关EF4.1的使用与探索将在之后一段时间为大家奉上。今天为大家带来如何得到EF查询所生成的SQL。
在EF 4和EF 3.5 SP1中,我们可以使用ToTraceString()方法得到EF查询所生成的SQL。
{
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为:
[Extent1].[ParentID] AS [ParentID],
[Extent1].[Name] AS [Name]
FROM [dbo].[Parent] AS [Extent1]
WHERE N'Lingzhi'=[Extent1].[Name]
在EF 4.1中,我们可以直接调用DbQuery<>的ToString()方法得到所生成的SQL。
{
var people = from p in context.People
where p.PersonID > 100
select p;
string sql = people.ToString();
}
所生成的SQL是:
[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得到的实现是这样的:
{
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
有时我们的实体只需要显示,无需更新,所以为了提高性能,我们不需要实体被EF context追踪。此时可以使用NoTracking的查询来得到实体,这样实体的状态会是Detached状态。
在EF3.5 SP1和EF 4中,我们可以这样来进行NoTracking查询:
{
context.People.MergeOption = System.Data.Objects.MergeOption.NoTracking;
var list = context.People.Where(p => PersonID > 100).ToList();
}
或使用ExecuteStoreQuery API来直接调用SQL命令来得到实体:
{
var query = context.ExecuteStoreQuery<Parent>("SELECT * FROM Parent WHERE Parent.ParentID > @ID", "TestDBEntities.Parents", System.Data.Objects.MergeOption.NoTracking, new SqlParameter("@ID", 100));
}
或使用Load方法得到相关实体:
{
context.ContextOptions.LazyLoadingEnabled = false;
var person = context.People.First();
person.Courses.Load(System.Data.Objects.MergeOption.NoTracking);
}
在EF 4.1中,我们可以使用新增的AsNoTracking方法:
{
var people = context.People.Where(p => p.PersonID > 100).AsNoTracking().ToList();
}
这里的AsNoTracking方法内部调用了过去的ObjectQuery.MergeOption来实现NoTracking查询。此方法(DbHelpers.CreateNoTrackingQuery)是AsNoTracking方法的核心:
{
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://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,哈哈!
在使用EF的集合类型的Navigation Property时,我时常需要只导入符合特定条件的实体对象,例如:Blog类和Post类存在一对多关系,即一个博客可以拥有多篇博文。现在我们想获得博客以及其相关博文中在今年1月1日之后发表的所有博文,可是之前EF版本所提供的Lazy Loading、Explicitly Loading和Eagerly 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) 利用匿名类,并且将过滤条件嵌入到返回的匿名类中:
{
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(2011, 1, 1))
}).ToList();
}
不过,此方法的缺点显而易见, 我们必须使用匿名类来包装实体对象,在数据绑定时会有挺多问题。
2) 使用多个query,让EF的跟踪机制帮助我们建立对象之间的联系。(EF4和EF4.1中,我们需要关闭Lazy Loading)
{
// 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(2011, 1, 1)
select p).ToList();
}
在两个query执行之后,EF的ObjectStateManager会自动建立Blog和Post之间的关系,如果我们访问blogs.First().Posts属性,将得到的都是今年1月1日之后创建的博文。
当然我想这两个方法在EF4.1中同样能成功。幸运的是,EF4.1提供了新的功能使我们可以在使用Explicitly Loading时添加过滤条件。
{
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(2011, 1, 1))
.Load();
// 或者使用String类型来标记Blog与Post的关系
context.Entry(blog).Collection("Posts")
.Query().Cast<Post>()
.Where(p => p.CreationTime >= new DateTime(2011, 1, 1))
.Load();
}
Collection()方法在这里返回DbCollectionEntry,Query()方法返回对应的IQueryable<T>对象。熟悉LINQ的同志们一定知道,得到IQueryable<T>了的话,一切好说,哈哈。EF4.1中,System.Data.Entity命名空间下的DbExtensions类中定义了不少LINQ的扩展方法,其中一个就是Load方法。用Reflector看了下Load方法的实现,其实就是调用IEnumerator.MoveNext遍历一遍集合:
{
while (enumerator.MoveNext())
{
}
}
当然这里如果我们不想导入这些相关的实体对象,也可以使用Count()方法得到符合条件对象的数量。这样我们得到的是实体的数量,而没有一个对应实体会被导入。
{
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



