EntityFreamWork和Mvc 精品知识点
定义了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/
EntityFreamWork和Mvc 精品知识点的更多相关文章
- ASP.NET MVC C#知识点提要
ASP.NET MVC C#知识点提要 本篇博文主要对asp.net mvc开发需要撑握的C#语言知识点进行简单回顾,尤其是C# 3.0才有的一些C#语言特性.对于正在学asp.net mvc的童鞋, ...
- spring mvc开发过程知识点记录
给一个客户做的一个小项目,需求就是输入类似一个短网址http://dd.yy/xxxx然后跳转到另外一个域名下的图书文件.(实际很多短网址站都提供API供调用吧,不过客户需求是他自己建立一个短网址服务 ...
- ASP.NET MVC 必备知识点杂谈
一 工程结构4个程序集 Microsoft.Web.Mvc --一些可以使用的,不确定的程序包System.Web.Mvc --主程序库下面两个列入3.5的Net框架了System.Web.Abs ...
- .Net Mvc框架知识点
一.实现Controller的依赖注入: 1.自定义继承DefaultControllerFactory 类的控制器工厂类并重写GetControllerInstance方法:(如:InjectCon ...
- spring mvc常用知识点总结
1.spring mvc是靠spring 启动的.通过springjar包的org.springframework.web.servlet.DispatcherServlet这个servlet类具体启 ...
- ASP.NET MVC知识点总结
一直都有把MVC的知识点总结出来的打算,今日终于得偿所愿.话不多说,开工!!! 一· MVC MVC设计模式->MVC框架(前端开发框架),asp.net(webform) aspx M:Mo ...
- Spring MVC知识点整理
网上Spring MVC相关知识点的介绍已经有很多了,但是大部分文章都是介绍其中的一部分知识点. 本文希望能够向读者做一个基本整体的介绍,首先我们先来了解下Spring MVC的基础接口和组件. ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出
本文示例代码下载: 链接:http://pan.baidu.com/s/1jHBdgCA 密码:hzh7 ps:Vs数据库脚本在解压目录下,修改web.config数据库链接,示例代码包含:导入,导出 ...
- MVC的简单初步学习(2)
今天似乎一切是正常的,我们的课依旧在进行着,但是恍惚脑海中并没有那样的平静,不知道在想些什么?而且今天是学习MVC的初步开始,我应该认真地学习才是正确的啊.但是我并不糊涂,今天是周一,也就是刚开始上课 ...
随机推荐
- sqlserver 大文件脚本执行
sqlserver2008中需要执行大文件的脚本,查询分析器中打不开,需要用到sql命令,开始使用osql命令,不过提示对应sqlserver2008中的驱动找不到(具体原因未分析-空闲时在处理),使 ...
- Python快速入门学习笔记(三)——函数的定义与调用
定义函数 Python中定义函数的格式为: def fun([参数列表]): ... 函数在执行到return语句时结束,并将结果返回.如果没有return语句,函数执行完毕后返回None. 例: d ...
- 如何找到Linux下常用命令的源码
Linux系统,常用命令的来源很多,有些命令是shell自带的,比如cd,通过执行help命令,可以查看当前系统所有的内置命令. 用type <cmd_name>来查看一个命令是否为内置命 ...
- 巧用Systemtap注入延迟模拟IO设备抖动
原创文章,转载请注明: 转载自系统技术非业余研究 本文链接地址: 巧用Systemtap注入延迟模拟IO设备抖动 当我们的IO密集型的应用怀疑设备的IO抖动,比如说一段时间的wait时间过长导致性能或 ...
- C#,PHP对应加密函数
require_once "JunDes.php"; $jDes=new JunDes(); echo $jDes->encode('98765'); //echo $jDe ...
- thymeleaf 模板布局
八.模板布局(Template Layout) 8.1 包含模板片段(Including template fragments) 定义和引用片段 我们通常想要从别的模板文件中调用一些模板片段,例如 页 ...
- sublime 设置localhost 2
最近sidebar用不了了,提示更新然后就自动卸载了: 研究了下其他方式实现: Sublime Text 2 Sublime Text 3 都可以使用: 菜单 --> Tools --> ...
- 修复ecshop商品重量BUG小数位增至五位
如果ECSHOP商品重量录入为1.499千克,数据库存储值为1.499:如果录入1.499克,存储值为1.显然数据保存有误差,虽然在快递运输中,此误差极小可以忽略不计,但从严谨的角度看,这是不合理的. ...
- envi中多波段图层叠加layer stacking
Basic Tools——layer stacking 选择投影和输出的文件 波段1-7波段图层都叠加在一个文件中了
- 微软职位内部推荐-Senior Data Scientist
微软近期Open的职位: Extracting accurate, insightful and actionable information from data is part art and pa ...