Entity Framework编写建议

一、查询

1.1 AsNoTracking() 非跟踪查询

在实体加上AsNoTracking()方法,返回的实体不会在System.Data.Entity.DbContext中进行缓存,因此能提高查询性能(数据量大,性能提升3到4倍)。
注:
1、实体不进行跟踪,所以修改实体后,进行SaveChanges()修改数据不会改变。
2、如果使用Select映射,不需要加AsNoTracking()。如:

Select(item=>new { item.Id,item.Name})

1.2 Any() 确定数据是否存在

使用Any(item=>item.Id==1)查询效率最高,FirstOrDefault次之,Count()最差(Any和Count相差几百倍)。

1.3 AsNonUnicode()

查询 (item=>item.Name="lee")(item=>item.Name==DbFunctions.AsNonUnicode("lee"))区别在于生成的Sql语句前者Name=N'lee',后者Name='lee',N是将字符串作为Unicode格式进行存储。
因为.Net字符串是Unicode格式,在上述SQL的Where子句中当一侧有N型而另一侧没有N型时,此时会进行数据转换,也就是说如果你在表中建立了索引此时会失效代替的是造成全表扫描。用 DbFunctions.AsNonUnicode 方法来告诉.Net将其作为一个非Unicode来对待,此时生成的SQL语句两侧都没有N型,就不会进行更多的数据转换,也就是说不会造成更多的全表扫描。所以当有大量数据时如果不进行转换会造成意想不到的结果。
因此在进行字符串查找或者比较时建议用AsNonUnicode()方法来提高查询性能。

1.4 真假分页

假:query.ToList().Skip((PageIndex - 1) * PageSize).Take(PageSize),把数据结果查询出放到内存中,然后进行分页。
真:query.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList(),会把参数传到数据库,生成分页Sql语句,在数据库查询。

1.5 按需返回列

Select(item => new { item.Id, item.CodeRuleId })

1.6 合理使用延迟加载

如果用不到导航属性中的数据,那么使用懒加载就行,不会加载不需要的数据到内存中。如果会在foreach中使用导航属性中的数据,那么最好是禁用懒加载,通过Include()方法,一次加载全部数据,防止在foreach多次和数据库进行交互。

1.7 IQueryable和IEnumerable的区别

IQueryable返回的是查询表达式,生成了SQL查询语句但是还没有与数据库进行交互。
IEnumerable则是已经执行查询数据库的操作且数据保存在了内存中。所以在进行条件拼接的时候一定要在IQueryable类型后面追加Where条件语句,而不是等到ToList之后再开始写条件。
错误:

db.Person.ToList().Where(item => item.Id == 1)

正确:

db.Person.Where(item => item.Id == 1).ToList()

二、排序

2.1 多字段组合排序

错误:.OrderBy(item=>item.Id).OrderBy(item=>itme.Name),生成Sql语句是Order By Name ASC。
正确:.OrderBy(item=>item.Id).ThenBy(item=>itme.Name),生成Sql语句是Order By Id ASC, Name ASC。
注:
1、另一种方法OrderBy(item=>new {item.Id,item.Name}),生成Sql语句同上。
2、降序使用OrderByDescending、ThenByDescending。

三、数据操作

3.1 批量新增、修改和删除

使用原生AddRange和RemoveRange时,会生成对应条数的Sql语句进行数据处理,可借助第三方类库实现一次性操作(并不生成多条Sql语句)。
第三方类库:Entity Framework Plus是一个提高实体框架性能并克服MUST-HAVE功能限制的库。
https://entityframework.net/zh-CN/tutorial/1000007/ef-plus

posted @ 2020-10-29 16:54  TC-MrLee  阅读(147)  评论(0编辑  收藏  举报