C# 面试手册

Entity Framework Core

请问对EFCore有了解吗?

Entity Framework Core是适用于.NET的新式物件资料库对应程式。其支援LINQ查询、变更追踪、更新以及结构描述移转。

EF Core透过[资料库提供者外挂程式模型]来搭配使用SQL Server/SQL Azure、SQLite、Azure Cosmos DB、MySQL、PostgreSQL及更多资料库。

说说EFCore查询的性能调优小技巧

如果说查询出来的数据,只是做展示,不做增删改查,可以在查询的时候,增加AsNoTracking()方法,可以提高性能,可以避免在内存中存在副本;建议在查询的时候,多使用Find()方法,会有限走内存缓存,如果内存已经存在,就不会去数据库中去操查询数据;

EFCore 如果通过数据生成实体和DbContext?

步骤如下:

  1. Nuget引入 如下程序集

  2. 在Vs中打开工具--nuget包管理器--程序包管理器控制台:命令执行:

    Scaffold-DbContext "Data Source=DESKTOP-63QE7M1;Initial Catalog=ZhaoxiEduDataBase;User ID=sa;Password=sa123" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Entity -Force -Context ZhaoxiDbContext -ContextDir /

注:命令参数应用如下:

Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer 
Install-Package Microsoft.EntityFrameworkCore.Tools

命令参数:

-OutputDir *** 实体文件所存放的文件目录
-ContextDir *** DbContext文件存放的目录
-Context *** DbContext文件名
-Schemas *** 需要生成实体数据的数据表所在的模式
-Tables *** 需要生成实体数据的数据表的集合
-DataAnnotations
-UseDatabaseNames 直接使用数据库中的表名和列名(某些版本不支持)
-Force 强制执行,重写已经存在的实体文件

说说对SaveChanges的理解

SaveChanges是以Context为维度的一次提交,对于数据库操作的一切动作,只要是在同一个Context实例,所有的操作,在调用SaveChanges方法后,统一体现到数据库中去;

说说对EFCore中EntityState的理解

因为EFCore对于数据库的所有操作都是通过上下文DbContext来完成的,且是通过SaveChanges方法统一落实到数据库中去的;EntityState是EFCore 在对数据库操作增删改的时候,记录当前被操作的数据对象和Context的关系,针对与不同的操作,对应的一个状态信息,一共五种状态;一共五种:

  • Detached = 0, 当前对象和context没有任何关系,没有被上下文跟踪
  • Unchanged=1, 当前对象被context跟踪,数据没有做任何修改
  • Deleted=2, 当前对象被context跟踪,且标记是数据删除,调用SaveChanges后将会从数据中删除;
  • Modified=3, 当前对象被context跟踪,且有属性数据被修改过,调用SaveChanges后将会从数据中修改;
  • Added=4 当前对象被context跟踪,且数据并没有存在数据库中,调用SaveChanges后将会新增到数据库中去;

说说什么是导航属性和引用属性

实体框架 中的导航属性提供了一种在两个实体类型之间导航关联的方法。导航属性在概念模型中由 NavigationProperty 元素 (CSDL) 定义。针对对象参与到其中的每个关系,各对象均可以具有导航属性。使用导航属性,您可以在两个方向上导航和管理关系,如果重数为一或者零或一,则返回EntityReference,或者如果重数为多个,则返回 EntityCollection。也可以选择单向导航,这种情况下可以删除导航属性。

efcore事务的几种方法?

  1. 默认事务(SaveChanges)

    默认情况下,如果数据库提供程序支持事务,单个 SaveChanges() 调用中的所有变更都会在一个事务中被提交。如果其中任何一个变更失败了, 那么事务就会回滚,没有任何变更会被应用到数据库。这意味着 SaveChanges() 能够确保要么成功保存,要么在发生错误时不对数据库做任何修改。

    关闭默认事务:context.Database.AutoTransactionsEnabled = false;

  2. DbContextTransaction

    使用方式

    BeginTransaction开启事务、Commit提交事务、Rollback回滚事务、Dispose销毁,如果用Using包裹的话,不再需要手动Rollback,走完Using会自动回滚。如果不用Using包裹事务,就需要在Catch中手动RollBack回滚,并且最好最后手动的Dispose一下。(如SameDbContext文件夹中的Test1和Test2方法)

    使用场景

    同一个上下文多个SaveChanges的方法(如:自增主键后续要用到)、SaveChanges和EF调用SQL语句混用

  3. 环境事务 TransactionScope

    使用方式

    new TransactionScope创建事务、Complete提交事务、 Transaction.Current.Rollback();回滚事务、Dispose销毁对象。如果用Using包裹的话,不再需要手动Rollback,走完Using会自动回滚。如果不用Using包裹事务,就需要在Catch中手动RollBack回滚,并且最好最后手动的Dispose一下。TransactionScope有三个属性:IsolationLevel(隔离等级),Timeout(超时),TransactionScopeOption(选项)

    用途

    • A. 同一个上下文的事务。(多个SaveChanges(自增主键后续用到的情况)、SaveChanges和EF调用SQL语句混用)(如Test1方法)
    • B. 多种数据库技术访问同一个数据库的事务 (如Test2方法)
    • C. 同一个数据库多个不同的上下文是支持的(如Test3方法)
    • D. 不同数据库的上下文是不支持的,(如Test4方法,开启msdtc服务的步骤: cmd命令→ net start msdtc ,然后发现报错:This platform does not support distributed transactions.说明目前Core平台下不支持分布式事务)

使用EF update 怎么保证在并发时数据正确?

1、RowVersion ( TimeStamp ) 时间戳

EF实现Rowversion 并发控制 需要借助 TimeStamp 标示 ,并且一个类只能有 一个此标示,标示的必须是byte[]类型。使用Rowversion会对整行数据进行并发检测。

2、 ConcurrencyCheck

有些时候并不需要控制针对整条记录的并发,只需要控制某个列的数据不会出现脏操作就ok,这个时候 就使用ConcurrencyCheck 。你必须将ConcurrencyCheck特性添加到实体需要控制并发的非主键属性上,使实体框架可以将所有标记的列包含到更新语句的Where子句中。

3、 DbUpdateConcurrencyException

您可以通过EF实体框架引发的DbUpdateConcurrencyException异常处理来解决冲突。