.net 面试题(包含.Net core)
1、 类 class和 接口 struct的区别?
类 Class可以被实例化,属于引用类型
接口Struct属于值类型
2、 C#中类成员的访问修饰符有哪些?
private : 私有成员, 在类的内部才可以访问。
protected : 保护成员,该类内部和继承类中可以访问。
public : 公共成员,完全公开,没有访问限制。
internal: 在同一程序集内可以访问。
3、 面向对象的三大特征是什么?/面向过程和面向对象的区别
封装,继承,多态
面向过程和面向对象都是解决问题的逻辑方法,分析问题既可以用面向对象的方法 来思考,也可以用面向过程方法来解决,但两者还是有一定区别
面向过程:是分析问题并解决问题所需要的步骤,强调是解决问题的步骤。可以先定义多个函数,在使用的时候逐步调用函数即可
面向对象:是把问题分解成多个对象,强调的是解决问题的行为表现
4、 抽象类和接口的区别?
接口支持多继承;抽象类不能实现多继承。
接口只能定义抽象规则;抽象类既可以定义规则,还可能提供已实现的成员。
接口是一组行为规范;抽象类是一个不完全的类
接口可以用于支持回调;抽象类不能实现回调,因为继承不支持
接口只包含方法、属性、索引器、事件的签名,但不能定义字段和包含实现的方法;抽象类可以定义字段、属性、包含有实现的方法
接口可以作用于值类型和引用类型;抽象类只能作用于引用类型。
5、 接口可以包含哪些成员?
接口可以包含属性、方法、索引指示器和事件,但不能包含常量、域、操作符、构造函数和析构
函数,而且也不能包含任何静态成员
6、 什么是装箱和拆箱?
从值类型转换到引用类型装箱。从引用类型转换到值类型拆箱
7、 C#中,哪些类型是值类型?哪些类型是引用类型?(数据类型)
C#的引用类型包括:数组、委托、接口、object、字符串、用户定义的类。
C#的值类型包括:数值类型、结构体、bool型、枚举、可空类型、用户定义的结构体。
8、 值类型和引用类型的区别?
值类型:占用空间固定、保存与复制的是值本身、使用typeof检测数据的类型、基本类型数据是值类型
引用类型:占用空间不固定、保存与复制的是指向对象的一个指针、使用instanceof检测数据类型、使用new()方法构造出的对象是引用型
9、 C#中的基本数据类型有哪些?
值类型:有符号整数(由小到大):sbyte、short、int、long 无符号整数(由小到大):byte、ushort、uint、ulong 浮点型:float、double、decimal
布尔型:bool
字符型:char
引用类型:string、object
10、 重写和重载的区别?方法的override和overload有什么区别?
重载:同类同名不同参,属于编译时多态。重载是在一个类中定义多个方法名相同的方法,表示一个行为有多种实现方式
重写:同名同参不同类,属于运行时多态。重写是用子类的方法来重写父类的方法,表示相同的方法在父类和子类中具有差异性
11、 构造函数是否可以被继承?是否可以被重写?
构造函数不可以继承,因此不能被重写,但可以被重载
12、 C#中,运算符“?”和“??”的区别是什么?
一个个问号(?)的运算符是指:可以为 null 的类型
如:
int? x = null;//定义可空类型变量
i=3?2:5 //还可为三元运算符
两个问号(??)的运算符是指null 合并运算符,合并运算符为类型转换定义了一个预设值,以防可空类型的值为Null
如:
int? y = x ?? 1000;//使用合并运算符,当变量x为null时,预设赋值1000
13、 C#中,用const和readonly修饰的字段有什么区别?
readonly (只读)和const(常量)都是用来标示常量的。
初始化赋值不同。
const修饰的常量必须在声明的同时赋值
14、 C#中,new有几种用法?
1)new 运算符:用于创建对象和调用构造函数。
2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。
3)new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型。
15、 C#中,ref和out在修饰方法参数时有什么区别?
ref和out都可以实现将一个指定的参数按照引用进行传递:
ref参数在传入方法之前必须进行初始化;而out参数在传入方法之前可以不用初始化。
ref参数在方法内部可以直接使用;而out参数在方法内部不能直接使用。
ref参数在方法内部可以使用也可以不使用;而out参数在方法返回之前必须对其赋值。
16、 C#中using有几种用法?
using指令,即引用命名空间。
using 定义对象的使用范围,即时释放对象。
using别名(using 别名=包括详细命名空间信息的具体的类型)
17、DataSet和DataReader的区别是什么?
DataSet(断开式的):数据集,表示内存中的“数据库”。DataSet在从数据库中读取数据时是“面向非连接的”,即DataSet在读取数据的那一刻会与数据库进行连接,然后会一次性把数据 库中所有的表以及数据读取到内存中,然后便断开数据库连接。
DataReader(连接式的):数据读取器。DataReader在从数据库中读取数据时是“面向连接的”,即DataReader在读取数据时是从数据库中一行一行读取,每次只会从数据库中读取一行 数据(类似于数据库游标的行为),直到读完最后一行之后,才断开数据库连接。在整个读取的过程中,必须保持与数据库的连接处于打开状态。
18、Server.Transfer与Response.Redirect有什么区别?
Server.Transfer方法把执行流程从当前的ASPX文件转到同一服务器上的另一个ASPX 页面,调用Server.Transfer时,当前的ASPX页面终止执行,执行流程转入另一个ASPX页面,但 新的ASPX页面仍使用前一ASPX页面创建的应答流。
Response.Redirect则是客户端第一次请求服务器返回状态代码302及新URL,客户端再次请求新URL,服务器再返回新页面,比Server.Transfer多一次应答
19、ASP.NET 中页面之间传递值的几种方式?
session cookie Application Request.QueryString
20、ASP.NET中调用Web Service的方法有哪些?
WebService的访问形式主要有:SOAP调用、XMLHTTP POST、GET调用、
MicroSoft.XMLDOMC调用、webbehavior.htc调用
21、Web Service有哪些优点?
Web Service是基于XML的,与具体的语言和平台无关,故可以实现跨平台、跨语言通信。
Web Service是采用SOAP协议(简单对象访问协议)进行通信的,该协议基于HTTP协议,故可以实现跨防火墙通信。
22、ASP.NET中的六大对象有哪些?
1.Response 2.Request 3.Server 4.Application 5.Session 6.Cookie
23、写出一条Sql语句: 取出表A中第31条到第40条记录(SQL Server, 以自动增长的ID作为主键, 注意:ID可能不是连续的)。
select *from(select row_number() over(order by ID asc)as id1,* from 表名)t where t.id1>30 and t.id1<=40
24、数据库索引是什么?有什么作用?
索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构
意义就是通过缩小一张表中需要查询的记录(行)的数目来加快搜索的速度。
25、SQL Server中索引的分类及区别?主键索引、聚集索引、非聚集索引聚集索引和非聚集索引的区别
1.聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个。
2.聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续。
3.聚集索引查询数据速度快,插入数据速度慢;非聚集索引反之。
26、什么是事务?它有哪些特性?
事务:所谓事务就是用户定义的一个数据库操作系列,这些操作要么全不做要么全做,是一个不可分割的工作单位。
事务有四个特性,分别是:原子性、一致性、隔离性、持续性
27、在SQL Server中union和union all的区别?
⒈UNION 和 UNION ALL 关键字都是将两个结果集合并为一个,但这两者从使用和效率上来说都有所不同。
⒉对重复结果的处理:UNION 在进行表链接后会筛选掉重复的数据,UNION ALL 不会去除重复的数据。
⒊对排序的处理:UNION 将会按照字段的顺序进行排序;UNION ALL 只是简单的将两个结果合并后就返回。
⒋从效率上说,UNION ALL 要比 UNION 快很多,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序的话,那么就使用 UNION ALL。
28、SQL Server中,有一张学生成绩表,有三个字段:学生ID,学生姓名,考试成绩。如何查询出成绩排在前三名的学生?(注意:可能会有并列名次)
select * from te where fenshu in (select top 3 fenshu from te group by fenshu order by fenshu desc)order by fenshu desc
29、SQL Server中排名函数有哪些?以及它们的区别?
ROW_NUMBER、RANK、DENSE_RANK、NTILE
ROW_NUMBER 函数实际上是一个序列,每个分组内都会创建一个序列,序列从1 开始,按照顺序依次 +1 递增。
RANK 函数用于排名时,不会返回连续的整数。RANK 函数的语法是:在分组内,按照特定的顺序排名,序号从 1 依次递增,排名函数以 tie 为单位,每个 tie 中的所有行的排名是相 同的,排名可能是不连续的。
DENSE_RANK 函数用于排名时,会返回连续的整数。每个 tie 占用一个排名,每个 tie 中的所有行的排名是相同的。排名值是连续的
在每个分组中,NTILE 按照指定的顺序,把数据行分为 N 个小组(tile),NTILE 返回小组编号。在每个分组内,具有相同的小组编号的数据行,位于同一个小组。
30、使用递归计算1~100之间整数的和
function getSum(n) {
if (n === 1) {
return 1;
}
//返回 n 和前 n-1 的和相加
return n + getSum(n - 1);
}
var s = getSum(100);
console.log(s);
31、冒泡排序
冒泡排序是一种对数据排序的方式.
从头开始,每一个元素和它的下一个元素比较,如果它大,就将它与比较的元素交换,否则不动.这意味着,大的元素总是在向后慢慢移动直到遇到比它更大的元素.所以每一轮交换完成都能将最大值冒到最后.就像是从河里冒出来的泡泡一样,泡泡刚刚在水底还很小,越往上越大.
下面就看一下具体实现:
static void Main(string[] args)
{
int temp = 0;
int[] arr = new int[] { 5, 3, 4, 6, 9, 1, 2, 7, 8 };
for (int i = 0; i < arr.Length - 1; i++)
{
for (int j = 0; j < arr.Length - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
Console.WriteLine("排序后的数组:");
foreach (int item in arr)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
32、ADO.NET中如何避免SQL注入漏洞的?
利用 sql 关键字对网站进行攻击。过滤关键字’等
33,在< a >标签中target的作用
< a > 标签的 target 属性规定在何处打开链接文档。分为4种,_blank,_self,_parent,_top
_blank 在新窗口中打开被链接文档。
_self 默认。在相同的框架中打开被链接文档。
_parent 在父框架集中打开被链接文档。
_top 在整个窗口中打开被链接文档。
34、简述三层架构层与层之间的关系、以及优缺点?
表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)
DAL–>BLL–>UI
优点:
1、可以降低层与层之间的依赖;
2、有利于标准化;
3、利于各层逻辑的复用。
缺点:
1、 降低了系统的性能。
2、 有时会导致级联的修改。
3、 增加了代码量,增加了工作量
35、设计模式
单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式
原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
36、ExecuteScalar 和 ExecuteNonQuery 的区别
ExecuteNonQuery:返回受影响的行数。
ExecuteScalar:返回结果集的第一行第一列,忽略其他行
37、进程和线程分别该怎么理解?
进程:进程是比线程大的程序运行单元,都是由操作系统所体会的系统运行单元,一个程序中至少要有一个进程,一个进程中,至少要有一个线程线程:线程的划分尺度要比进程要小,进程拥有独立的内存单元,线程是共享内存,从而极大的提高了程序的运行效率,同一个进程中的多个线程可以并发执行
38、能用foreach遍历访问的对象需要实现?
IEnumerable接口或声明GetEnumerator方法的类型
注:不一定要实现IEnumerable接口,但一定要实现GetEnumrator方法。
39、Redis支持哪些数据类型?
string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
40,在c#中sleep() 和 wait() 有什么区别?
①. sleep是线程类Thread 的方法,它是使当前线程暂时睡眠,可以放在任何位置。
而wait是Object类的方法,它是使当前线程暂时放弃对象的使用权进行等待,必须放在同步方法或同步块里。
②. Sleep使用的时候,线程并不会放弃对象的使用权,即不会释放对象锁,所以在同步方法或同步块中使用sleep,一个线程访问时,其他的线程也是无法访问的。
而wait是会释放对象锁的,就是当前线程放弃对象的使用权,让其他的线程可以访问。
③. 线程执行wait方法时,需要另一个线程调用notify进行唤醒。
而sleep只是暂时休眠一定时间,时间到了之后,自动恢复运行,不需另外的线程唤醒。
41,堆和栈的区别?
1.申请方式的不同。栈由系统自动分配,而堆是人为申请开辟;
2.申请大小的不同。栈获得的空间较小,而堆获得的空间较大;
3.申请效率的不同。栈由系统自动分配,速度较快,而堆一般速度比较慢;
4.存储内容的不同。栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;
5.底层不同。栈是连续的空间,而堆是不连续的空间。
42、.net的错误处理机制是什么?
.net错误处理机制采用 try->catch->finally 结构,发生错误时,层层上抛,直到找到匹配的Catch为止。
43、CTS、CLS、CLR分别作何解释?CLR 提供了.NET 的哪些功能?(中间语言编译器、JIT 等等)
CTS即通用类型系统,它定义了如何在.NET Framework运行库中声明、使用和管理类型,同时也是.NET Framework运行库支持跨语言集成的一个重要组成部分。
CLS 即公共语言规范,它是许多应用程序所需的一套基本语言功能
CLR 即公共语言运行库,是.NET Framework 的基础,可以将其看作一个在执行时管理代码的代理,它提供了内存管理、线程管理和远程处理等核心服务,并且还强制实施严格的类型安全以及可提高安全性和可靠性的其他形式的代码准确性。
功能:内存管理 版本发布 汇编指令
44,GC是什么? 为什么要有GC?
1.GC是垃圾收集器。程序员不用担心内存管理,因为垃圾收集器会自动进行管理.
2 .NET的GC机制有这样两个问题:首先,GC并不是能释放所有的资源。它不能自动释放非托管资源。
45、如何在ASP.NET Core中激活Session功能?
首先要添加session包. 其次要在configservice方法里面添加session。然后又在configure方法里面调用 usesession。。
46、什么是中间件?
中间件在这里是指注入到应用中处理请求和响应的组件。是通过多个委托来嵌套形成的一个俄罗斯套娃!
或者微软官方原话:
中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
选择是否将请求传递到管道中的下一个组件。
可在管道中的下一个组件前后执行工作。
请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。
47、Applicationbuilder的Use和Run方法有什么区别?
这两个方法都在startup 类的configure方法里面调用。都是用来向应用请求管道里面添加中间件的。
Use方法可以调用下一个中间件的添加,而run不会。run是终结式的;
48、什么是ASP.NET Core?
首先ASP.NET Core可以说是 ASP.NET的升级版本。它遵循了.NET的标准架构,是一个基于.NET Core的
Web开发框架, 可以运行于多个操作系统上。它更快,更容易配置,更加模块化,可扩展性更强。
49、ASP.NET Core 中AOP的支持有哪些?
aop就是面向切面的编程,.netcore里通过Filter来支持;
分别有AuthorizeFilter ResourceFilter ActionFilter ExceptionFilter ResultFilter,Filter也被称为拦截器!
50、ASP.NET Core Filter的注册方式有哪些?
方法注册:只对方法生效
控制器注册:对控制器中的所有方法生效
全局注册:对整个项目生效;
51、ASP.NET Core Filter如何支持依赖注入?
可以通过全局注册,支持依赖注入
通过TypeFilter(typeof(Filter)) 标记在方法,标记在控制器
通过ServiceType(typeof(Filter))标记在方法,标记在控制器,必须要注册Filter这类;
TypeFilter和ServiceType的本质是实现了一个IFilterFactory接口;
52,ASP.NET Core 如何和读取配置文件中的内容?
可以有两种方式,可以通过IConfiguration接口来读取;
也可以使用IOptionsSnapshot来读取,需要先根据配置文件结构一致的实体对象,来绑定到对象中去;
必须保证:DBConnectionOption和配置文件的内容结构一致;
53、ASP.NET Core有哪些好的功能?
第一是依赖注入。
第二是日志系统架构。
第三是引入了一个跨平台的网络服务器,kestrel。可以没有iis, apache和nginx就可以单独运行。
第四是可以使用命令行创建应用。
第五是使用appsettings来配置工程。
第六是使用startup来注册服务。
第七是更好的支持异步编程。
第八是支持web socket和signal IR。
第九是对于跨网站的请求的预防和保护机制。
54、ASP.NET Core跟ASP.NET比较有哪些更好的地方?
第一是跨平台,它可以运行在三大操作系统上面,windows, Linux和MAC。
第二是对架构本身安装没有依赖,因为所有的依赖都跟程序本身在一起。
第三是ASP.NET Core处理请求的效率更高,能够处理更多的请求。
第四是ASP.NET Core有更多的安装配置方法。
55、什么是meta packages?
Meta packages是指包含所有ASP dot net code依赖的一个包。叫做Microsoft.AspNetCore
56、ASP.NET Core应用能够跟ASP.NET4.x架构一起工作吗?
可以。ASP.NET Core应用可以跟标准的dot net 库一起工作。
57、什么是ASP.NET Core的startup 类?
startup 类是ASP.NET Core应用的入口。所有的ASP.NET Core应用必须有这个类。这个类用来配置应
用。这个类的调用是在program main函数里面进行配置的。类的名字可以自己定义
58、startup 类的configservice方法有什么作用?
用以配置应用的服务;在这个方法里我们可以添加一些service进入依赖注入容器。
比如数据库连接池,mvc,swagger,controllers,filter,jwt,请求头,以及自己定义的接口。
(服务是一个提供应用功能的可重用组件。 在 ConfigureServices 中注册服务,并通过依赖关系注入 (DI) 或 ApplicationServices 在整个应用中使用服务。)
最重要的参数为:IServiceCollection services
59、startup 类的configure方法有什么作用?
用以创建应用的请求处理管道;这个方法来定义整个应用如何响应HTTP请求。它有几个比较重要的参数,IApplicationBuilder,Hosting
environment, logfactory, 在这里我们可以配置一些中间件用来处理路径,验证和session等等
60、ASP.NET Core管道里面的map拓展有什么作用?
可以针对不同的路径添加不同的中间件。
61、ASP.NET Core里面的路径是如何处理的?
路径处理是用来为进入的请求寻找处理函数的机制。所有的路径在函数运行开始时进行注册。
主要有两种路径处理方式, 常规路径处理和属性路径处理。常规路径处理就是用MapRoute的方式设定
调用路径,属性路径处理是指在调用函数的上方设定一个路径属性。
62、ASP.NET Core工程里面有多少个工程文件?
Program, Startup ,launchsetting,appsettings
63、什么是ASP.NET Core里面的taghelper
Taghelper用来在服务器端使用Razor视图引擎创建html元素的。
64、什么是Razor页面?
是ASP.NET Core中支持ASP网页表格的一种开发模型。@page 作为页面的起始标志。。
Stringbulider的使用,最好制定合适的容量值,否则优于默认值容量不足而频繁的
65、说说.NET5中 __ViewStart文件的作用
在控制器在返回视图的时候,开始替换视图引擎的时候,从_ViewStart.cshtml 开始,来初始化展示的视
图界面;试图views的入口文件。
66、如何在Razor页面中实现数据模型绑定?
使用bindproperty属性。
67、如何在Controller中注入service?
在config services方法中配置/注册这个service。
在controller的构造函数中,添加这个依赖注入
68、描述一下依赖注入后的服务生命周期?
在ASP.NET Core中,我们不需要关心如何释放这些服务, 因为系统会帮我们释放掉。有三种服务的生命周期。
单实例服务, 通过add singleton方法来添加。在注册时即创建服务, 在随后的请求中都使用这一个服务。
短暂服务, 通过add transient方法来添加。是一种轻量级的服务,用于无状态服务的操作。
作用域服务,一个新的请求会创建一个服务实例。使用add scoped方法来添加。
69、ASP.NET Core中如何读取静态文件?
可以通过中间件UseStaticFiles来配置读取静态文件;
70,ASP.NET Core项目如何设置IP地址和端口号?
可以使用Properties文件夹下的launchSettings配置文件来配置不同的启动方式的时候,分别配置IP和端口号。
71、说说Core WebApi特性路由。
在Core WebApi中,每一个Api必须指定特性路由,即在Api或者控制器上标记特性
Route("api/[Controller]/Api");访问Api,就按照这个格式访问;
72、如何解决跨域问题?
三种方式:
1.后台模拟Http请求,既然是浏览器的行为,就避开浏览器,先来一个同源的服务器去请求,然后由服务器模拟http请求去请求到Core WebApi的资源,然后响应给前端;
2.JSONP,思路:通过html部分标签发起请求,比方说 等等,发起请求是可以避开同源策略的,使用这些标签发起请求,然后带有一个回调函数,然后得到请求后,把回调函数之心一次,把数据解析后使用;
3.服务端允许跨域,多种方式,可以自己定义中间件支持跨域,只要把响应的Response的头信息Header中写入“Access-Control-Allow-Origin” 即可支持跨域;如果需要让所有的Api都 支持跨域,就可以写一个中间件从管道处理模型中去支持跨域,如果要选择性的支持跨域,可以使用ActionFilter来完成,也可以通过Cors(ASP.NET Core中提供的中间件,可以支持配置不同的跨域规则)来配置支持跨域;
73、说说你了解到的鉴权授权技术。
1.传统的授权技术:通过Session、Cookie完成授权;实现特点: 让无状态的http请求,变的有状态,让第一次请求和第二次请求之间产生联系,第一次请求进入服务器,在服务器写入一组session,然后返回sessionId给客户端存在Cookie,第二次请求,从cookie中取到SessionId,传递给服务器,服务器鉴别SessionId,如果是上一次来的SessionId,就认为之前来请求过;就认为有权限;
2.流行鉴权授权方式:Token授权,在Core WebApi中主要就是JWT和IdentityServer4;都是独立的授权中心,授权后颁发token,然后客户端带着token去请求Api,Api方验证Token,验证通过就有权限,验证不通过就没有权限;
74、说说EFCore查询的性能调优小技巧。
(1).使用DbContext池
(2).优先使用异步方法
(3).批处理语句
(4).关闭状态追踪,AsNoTracking()
(5).关闭状态同步,context.ChangeTracker.AutoDetectChangesEnabled = false
75、说说对SaveChanges的理解。
SaveChanges是以Context为维度的一次提交,对于数据库操作的一切动作,只要是在同一个Context实例,所有的操作,在调用SaveChanges方法后,统一体现到数据库中去;
76、说说对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后将会新增到数据库中去;
77、说说什么是EF中导航属性和引用属性。
EF Core导航属性分为三种:
集合导航属性:主表中对子表相关数据的引用
引用导航属性:子表中对主表数据的引用
反转导航属性:一个导航属性对应的另一端的导航属性
以上就是我整理出来的一些面试题,后续也会继续补充。

浙公网安备 33010602011771号