定义了DbRepository<TEntity>:IRepository<TEntity> ,SimpleDbContext继承了DbContext, UnitOfWork:IUnitOfWork,

当已经存在数据库的时候,可以使用Entity Framework Power Tools 来反向生成Model,和Map对象,非常方便

张占岭 的ef系列:http://www.cnblogs.com/lori/archive/2013/01/31/2887396.html

.NET 开源项目 http://www.cnblogs.com/acdomain/p/2014-csharp-top-25.html

蒋金楠(Artech) 很多系列都不错

领域驱动设计与entityFreamwork http://www.uml.org.cn/zjjs/201301285.asp#2

引用 http://diaosbook.com/Post/2012/12/9/performance-issue-in-select-one-or-few-colums-via-entityframework

自从我用了EF,每次都很关心是否有潜在的性能问题。所以每次我写LINQ查询,都会使用SQL Profiler看一下实际生成的SQL语句,以便发现潜在的性能问题。也强烈建议大家这么去做,以免日后软件大了出了问题很难查。

一、只选择某列或某些列

有些时候,在C#里写LINQ虽然看着舒服,但性能不一定好,所以有必要做一些调整。比如这种情况:

我需要知道一篇文章的点击数,仅此而已,我可能会写:

context.Post.FirstOrDefault(p => p.Id == postId).Hits;
或者:

context.Post.Find(postId).Hits;
我期待着他们只去数据库里筛选Hits这一列的数据,然而,通过SQL Profiler会发现,这两条语句居然把全部列都给select出来了,访问Hits的操作实际是在内存中进行的。

虽然小表看不出性能问题,但万一你的表里有一列是存文件字节流(byte)的,那这样的操作可能会很慢,并且消耗额外的网络传输,所以不能忽视这个问题。

其实,我只要稍作调整,就能避免这个问题,但会LINQ语句难看一点:

context.Post.Where(p => p.Id == postId).Select(p => p.Hits).FirstOrDefault();
LINQ to SQL最终生成的native sql是这样的:

exec sp_executesql N'SELECT TOP (1)
[Extent1].[Hits] AS [Hits]
FROM [dbo].[Post] AS [Extent1]
WHERE [Extent1].[Id] = @p__linq__0-61EDA559F804'
真正的只select了Hits一个字段。

二、ToList()的问题

其实EF很多时候的性能问题都是关系到查询执行时机的。我们通常的意图是,首先建立一个查询表达式,只是build,而不execute。执行的时机是用到这个表达式结果的时候才去执行。

在公司码程序的时候,我看到好多同事用EF,写完查询喜欢直接调用ToList()方法。有时候这会造成很大的性能问题。因为单纯声明一个linq表达式并不会立即执行SQL查询,然而一旦在后面加上ToList(),就会立即去执行。如果你只是想根据条件选择其中一些数据,而非全部的话,那ToList()以后再筛选,就是从内存里执行了,并不是把你的条件转换成sql的where语句去执行。

var query = from ..... // 建立查询,但不执行
...
var result = query.ToList(); // 立即执行查询
所以,你应当尽量避免从ToList()后的结果中再去查找自己想要的元素。

三、IQueryable, IEnumerable

在这两个接口的选择上,我偏向使用IQueryable。大部分时候这两个接口在使用上的表现都是一致的,但如果你要做的是一个不确定的查询,意思是这个查询表达式不是一次性确定的,对于它的结果可能由别的类来选择到底select哪些东西,这时候就要用IQueryable。

比如我有一个数据层方法:

public IEnumerable<EdiBlog.Core.Entities.Post> GetAllPost()
{
    return context.Post;
}
很显然,它会被系统中的其他方法调用,而这些调用者希望得到的结果都各不相同。通常的操作就是再拼一个where语句上去:

var myResult = postDa.GetAllPost().Where(...)
但这时,很不幸的是,where语句中的条件并不是转换为native sql去执行的,它是在内存中筛选的。这是一个比较阴的性能问题。所以文章一开始我就建议大家多用SQL Profiler看看自己的LINQ是怎么执行的。

如果把返回类型换成IQueryable,那么你的where语句就可以转化为SQL执行。

public IQueryable<EdiBlog.Core.Entities.Post> GetAllPost()
{
    return context.Post;
}
关于这两个接口,在屌丝论坛StackOverflow上有一个比较好的帖子,大家可以自己看一下:

http://stackoverflow.com/questions/252785/what-is-the-difference-between-iqueryablet-and-ienumerablet

“IEnumerable: IEnumerable is best suitable for working with in-memory collection. IEnumerable doesn’t move between items, it is forward only collection.

IQueryable: IQueryable best suits for remote data source, like a database or web service. IQueryable is a very powerful feature that enables a variety of interesting deferred execution scenarios (like paging and composition based queries).”

在MSDN论坛上也有个比较直观的答案:

IQueryable returns a "queryable" that is a query you could still be enriched before really sending it to the server.

IEnumerable returns a list that is the actual querying took place and you get the results. ToList is isued to force running the query and returning these enumerable results...

So in short :
- use IQueryable if you want to return a base query that could be further enhanced before running it server side (by enumerating its items)..
- use IEnumerable/ToList if you want to return a list that has been retrieved from the db

四、计算个数,Count()和Count

这个是最容易被坑,也是非常严重的一个性能问题。当我们需要统计符合某条件的记录的条数时,我们希望SQL语句是SELECT COUNT(*) ... 这种形式的。然而下面这个看似很自然的写法却会导致不希望的结果:

context.Category.FirstOrDefault(p => p.Name == categoryName).Posts.Count;
这是我博客里用来统计某分类下文章数目的语句,当然,因为发现性能问题,现在已经不是这么写了。它产生的SQL并不是SELECT COUNT,而是分成2条。下面是SQL Profiler抓到的:

exec sp_executesql N'SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[DisplayName] AS [DisplayName]
FROM [dbo].[Category] AS [Extent1]
WHERE [Extent1].[Name] = @p__linq__0)',@p__linq__0=N'ASPNET'

exec sp_executesql N'SELECT
[Extent2].[Id] AS [Id],
[Extent2].[Title] AS [Title],
[Extent2].[Slug] AS [Slug],
[Extent2].[PubDate] AS [PubDate],
[Extent2].[PostContent] AS [PostContent],
[Extent2].[Author] AS [Author],
[Extent2].[CommentEnabled] AS [CommentEnabled],
[Extent2].[IsPublished] AS [IsPublished],
[Extent2].[Hits] AS [Hits],
[Extent2].[Rators] AS [Rators],
[Extent2].[Rating] AS [Rating],
[Extent2].[ExposedToSiteMap] AS [ExposedToSiteMap],
[Extent2].[DisplayFrom] AS [DisplayFrom],
[Extent2].[DisplayTill] AS [DisplayTill],
[Extent2].[LastModifyOn] AS [LastModifyOn],
[Extent2].[PublishToRss] AS [PublishToRss]
FROM  [dbo].[PostCategory] AS [Extent1]
INNER JOIN [dbo].[Post] AS [Extent2] ON [Extent1].[PostId] = [Extent2].[Id]
WHERE [Extent1].[CategoryId] = @EntityKeyValue1',N'@EntityKeyValue1 uniqueidentifier',@EntityKeyValue1='3FEB11A2-6E36-4DCE-8C02-614BEF7ACC62'
可以看到,EF做了两件事,第一件事是查找Name为"ASPNET"的Category,然后用这个Category的Id去找它所有的Post,最后做Count的其实是.NET在内存里进行的。这显然把我们不需要的信息都给SELECT出来了。我们只需要一个Count,为毛会这么复杂呢?

回顾第一条我所讲过的。不难发现。在FirstOrDefault(...)之后访问的属性,都是在内存里进行的。所以,当我们访问Category.FirstOrDefault(p => p.Name == categoryName)的时候,就生成了第一条SQL语句。紧跟其后的“.Posts”是Category对象的导航属性,EF会用lazy load去加载这个category所有的post,所以就生成了第二条SQL语句。再紧接其后的Count就自然而然在内存里进行了。

如果要让代码尽量去生成LINQ to SQL,有个很简单的原则,就是尽量用LINQ、Lambda表达式,这样EF才可能帮我们翻译。C#里的Count有两种。Enumerable.Count()是方法,List.Count是属性。一旦一个东西变成了List,你再去Count,就必定是在内存里进行的了。

所以,在EF中,要进行Count操作,应该这样写:

context.Post.Count(p => p.Categories.Any(q => q.Name == categoryName));
这时,Count()接受了一个lambda表达式,LINQ to SQL就能准确翻译为“SELECT COUNT”了:

SELECT [GroupBy1].[A1]  AS [C1]
FROM   (
           SELECT COUNT()      AS [A1]
           FROM   [dbo].[Post]  AS [Extent1]
           WHERE  EXISTS (
                      SELECT  AS [C1]
                      FROM   [dbo].[PostCategory] AS [Extent2]
                             INNER JOIN [dbo].[Category] AS [Extent3]
                                  ON  [Extent3].[Id] = [Extent2].[CategoryId]
                      WHERE  ([Extent1].[Id] = [Extent2].[PostId])
                             AND ([Extent3].[Name] = 'ASPNET')
                  )
       )                AS [GroupBy1]
现在性能要明显好很多~

Entity Framework 6 (& SQL Server Compact) (5)–Entity Framework 6 extensions

This is a list of some of all the nice Entity Framework 6 extensions out there that expand the functionality of the Entity Framework 6 runtime. Code generator tools and Frameworks using Entity Framework are not included here, only libraries that extend DbContext or similar.

The EF team has lists of Tools and 3rd party EF providers here: http://msdn.microsoft.com/en-us/data/ee712907

Please let me know if I have missed anything, and I will add it to the list.


Store Functions for EntityFramework CodeFirst 
  
Why: This project uses the basic building blocks to build end to end experience allowing using TVFs in Linq queries and invoking stroed procedures without having to drop down to SQL. 
Project: https://codefirstfunctions.codeplex.com/ 
NuGet: Coming soon


Interactive Pre-Generated Views for Entity Framework 6 

Why: An alternative is a solution where views are created dynamically only when needed (i.e. views don't exist or are out dated) and then persisted and made available for use by other instances of the same application (be it running in parallel or the same application after a restart). This is exactly the problem Interactive Pre Generated Views project is trying to solve. 
Project: https://efinteractiveviews.codeplex.com/ 
NuGet: https://www.nuget.org/packages/EFInteractiveViews


Entity Framework 6 Contrib 

Why: https://ef6contrib.codeplex.com/documentation 
Project: https://ef6contrib.codeplex.com/ 
NuGet: https://www.nuget.org/packages/EF6.Contrib/

Entity Framework Extended Library

Why: Batch Update and Delete, Future Queries, Query Result Cache, Audit Log 
Project: https://github.com/loresoft/EntityFramework.Extended 
NuGet: https://www.nuget.org/packages/EntityFramework.Extended/ and 
http://www.nuget.org/packages/EntityFramework61.Extended 

EntityFramework.Utilities 

Why: EntityFramework.Utilities provides some batch operations for using EF that the EF team hasn't yet added for us. (CUD) 
Project: https://github.com/MikaelEliasson/EntityFramework.Utilities 
NuGet: https://www.nuget.org/packages/EFUtilities/


EntityFramework.BulkInsert

Why: Bulk insert extension for EntityFramework. Insert large amount of data over 20 times faster than regular insert. Supports DB first and code first. 
Project: https://efbulkinsert.codeplex.com/ 
NuGet: https://www.nuget.org/packages/EntityFramework.BulkInsert-ef6


Trackable Entities 
Why: Visual Studio 2012 and 2013 project templates and NuGet packages for client-side entity change-tracking and server-side persistence with Entity Framework extensions. 
Project: https://trackable.codeplex.com/ 
NuGet: https://www.nuget.org/packages/TrackableEntities.EF.6/

最新文章

  1. msdia80.dll文件出现在磁盘根目录下的解决方案
  2. winform退出或关闭窗体时弹窗提示代码:转
  3. Java开发高薪之路__大纲篇
  4. Delphi关于记录文件的操作
  5. IE6下div遮盖select的最优解决方案
  6. Comparison method violates its general contract
  7. jQuery执行请求demo
  8. solr可用于集群的搜索 【转】
  9. linux下利用sed重命名文件
  10. centos 6.6 ios镜像文件 下载 官网和阿里云两种方式教你下载
  11. numpy教程:统计函数Statistics
  12. 小谈UAT(验收测试)
  13. 大数据之 Spark
  14. java-抽象类的成员特点
  15. LVS健康检查脚本
  16. linux上搭建ftp、vsftp, 解决访问ftp超时连接, 解决用户指定访问其根目录,解决ftp主动连接、被动连接的问题
  17. Java虚拟机--虚拟机字节码执行引擎
  18. centos7 安装oracle jdk 与openjdk 实现切换
  19. SQL Server数据库定时备份解决方案
  20. restful_framework之视图组件

热门文章

  1. 第九篇、Swift的基本使用
  2. 重建Mac系统的文件打开方式
  3. Linux 内核 链表 的简单模拟(1)
  4. spring 计划任务:cron表达式
  5. KnockoutJS(1)-数据模型
  6. BroadcastReceiver
  7. Asp.net Response.Redirect with post data
  8. html5画四边形
  9. 設定 Bootstrap/SASS/Bower/gulp (Windows平台)
  10. ISBN