EF的查询效率如何优化?
EF(Entity Framework)是一个对象关系映射框架,可以用来简化与数据库交互的代码。在进行查询时,以下是一些优化EF查询效率的方法:
使用延迟加载:EF默认使用延迟加载(Lazy Loading)来获取导航属性的数据。延迟加载可以避免不必要的查询和数据加载,因此可以提高查询性能。你可以通过配置来启用或禁用延迟加载。
使用预先加载:预先加载(Eager Loading)是在查询时一次性获取所有相关数据的技术。它可以避免多次查询数据库,从而提高查询性能。你可以使用Include()方法来实现预先加载。
使用筛选:筛选是通过条件过滤数据以获取所需数据的技术。使用筛选可以减少从数据库中检索的数据量,从而提高查询性能。你可以使用Where()方法来实现筛选。
避免多层嵌套查询:多层嵌套查询会导致查询性能下降。你可以尝试使用联接(Join)操作来减少嵌套查询。
使用索引:索引可以加速数据检索和查询操作。如果你的数据库中有大量的数据,使用索引可以显著提高查询性能。
使用存储过程:存储过程可以在数据库中进行预处理,从而提高查询性能。你可以使用EF来执行存储过程。
调用AsNoTracking()方法 实现非跟踪式的只读查询
什么是跨域问题?项目中具体怎么解决跨域的问题?
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。
基本上有三种主流的解决方案:
1、使用JSONP的方式:JSONP是一种比较古老的解决方案,这种方案首先没有兼容性问题,基本都可以使用,但是它所解决的问题比较有限,且对服务端接口有一定的要求
2、使用反向代理:这种方式目前使用相当普遍,就是在目标服务器和浏览器中间架一层服务器,我们称该服务器为代理服务器
3、使用跨域资源共享:这是一种新的解决跨域的方式,主要是通过设置特殊的响应头,来达到解除跨域限制的目的。跨域资源共享简称CORS(我们现在用这个),需要浏览器和服务器同时支持,目前所有的浏览器都支持,ie必须不能低于ie10
项目中有没有用到AOP?什么是AOP?有什么样的优势?
AOP(面向切面编程)是一种编程范式,它允许在程序运行时动态地横向增加新的行为,而无需修改现有代码。
AOP的核心思想是将应用程序分为多个关注点,每个关注点实现特定的功能,例如安全性、事务、日志记录、缓存等。
AOP的主要优势在于解耦和复用。通过使用AOP,可以将一些通用的功能集中在一个地方,而不是分散在整个应用程序中。这样,它可以让代码更加清晰易懂、易于维护,并且避免重复代码。
例如,假设您的应用程序需要记录每个方法的执行时间,您可以使用AOP创建一个切面,该切面在每次方法调用前记录开始时间,在方法调用后记录结束时间,并计算时间差。这样,您就可以将这个通用功能应用于整个应用程序,而无需在每个方法中重复代码。
项目中的ConfigureServices方法里面注入了哪些服务?什么作用?
CORS跨域服务
Authentication身份认证服务
Swagger的服务
Redis的服务
DbContext数据库上下文服务
控制器相关的服务(配置过滤器)
配置Autofac相关服务
还有自己项目的服务,如Service服务、Repository服务等
ASP.Net Core默认提供的跨平台的服务器是什么?具体负责做什么?
ASP.Net Core默认提供的跨平台的服务器是Kestrel服务器。Kestrel是ASP.Net Core的默认Web服务器,它是跨平台的,可以在Windows、Linux和macOS等操作系统上运行。
Kestrel是一个轻量级的服务器,专门为处理ASP.Net Core应用程序而设计。它负责处理HTTP请求和响应,支持HTTP/1.x和HTTP/2协议,并且具有异步处理请求的能力。Kestrel也可以与反向代理服务器(如Nginx或Apache)一起使用,以提高安全性和性能。
需要注意的是,虽然Kestrel是一个快速且可靠的服务器,但它并不适合直接暴露在公共网络上。在生产环境中,应该使用反向代理服务器(如Nginx或Apache)来保护Kestrel服务器。
为什么项目使用.Net Core进行开发? .Net Core有什么优势?
使用 .NET Core 进行项目开发有以下几个优势:
跨平台支持:.NET Core 能够在 Windows、macOS 和 Linux 等多个操作系统上运行,可以大大降低开发人员的学习成本和开发成本,提高代码复用性。
高性能:.NET Core 相比传统 .NET Framework 具有更高的性能,主要得益于其采用的基于运行时编译的 JIT 技术,同时采用了更加轻量级的架构设计。
依赖性管理:.NET Core 提供了强大的依赖性管理功能,可以方便地管理和维护项目所依赖的各种包和库。
开放源代码:.NET Core 是一个开放源代码的框架,这意味着开发人员可以在其基础上进行二次开发和定制,也能够更好地与其他开源框架和工具进行集成。
支持微服务架构:.NET Core 支持微服务架构,可以方便地构建分布式应用程序。
总的来说,采用 .NET Core 进行项目开发可以提高开发效率,降低成本,同时也能够得到更好的性能和可维护性。
WebService和WebApi区别?各自基于什么传输协议?
1)协议不同:
WebApi用的是HTTP协议,WebService用的是SOAP协议;
2)数据格式
WebApi可以自定义格式(int,string,xml等,标准是json)
WebService是xml数据格式
3)WebApi无状态(http是无状态协议,断开数据就丢失),比WebService更轻量级。 WebApi支持如get,post等http操作
项目中的Configure方法里面注入了哪些中间件?分别什么作用?
UseAuthentication 身份验证中间件
UseCors 跨域中间件
UseSession 会话缓存中间件
UseStaticFiles 静态文件中间件
UseAuthorization 授权认证中间件
UseSwagger swagger测试中间件
UseRouting 路由中间件
创建中间件管道中用到的Use, Run, 和 Map分别做什么用的?
Map用来定义一个管道可以处理哪些请求。
Use和Run用来定义管道,一个管道由若干个Use和一个Run组成,每个Use引入一个中间件,而Run是用来执行最终的核心应用逻辑。
用Use将多个请求委托链接在一起。 next参数表示管道中的下一个委托。 可通过不调用next参数使管道短路。
Run 委托不会收到 next 参数。 第一个 Run 委托始终为终端,用于终止管道。 Run 是一种约定。 某些中间件组件可能会公开在管道末尾运行的 Run[Middleware]
Map*扩展用作分支管道的约定
什么是依赖注入?什么是控制反转?
1.控制反转是一种在软件工程中解耦合的思想,调用类只依赖接口,而不依赖具体的实现类,减少了耦合。控制权交给了容器,在运行的时候才由容器决定将具体的实现动态的“注入”到调用类的对象中。
2.依赖注入是一种设计模式,可以作为控制反转的一种实现方式。依赖注入就是将实例变量传入到一个对象中去
控制反转思想可以指导我们如何设计出松耦合,更优良的程序,传统应用程序都是由于我们在类内部主动创建依赖对象 从而导致类与类之间 高耦合,难于测试,有了ioc容器以后我们可以把创建依赖对象的控制权交给了IOC容器,由容器注入组合对象,所以对象和对象之间是松耦合的;便于测试 ,最重要的是 使各个功能之间变得非常灵活。比如AutoFac,就是一个IOC容器
为什么要使用过滤器?过滤器的使用场景有哪些?
在 .NET Core 中,过滤器是一种用于在应用程序中实现“横切关注点”的技术。
过滤器可以在应用程序处理请求和响应的不同阶段中执行代码,并允许您在每个阶段上执行自定义逻辑。以下是过滤器在 .NET Core 中的一些使用场景:
身份验证和授权:授权过滤器可以用于实现身份验证和授权逻辑,例如在请求到达控制器或操作之前验证用户的身份或权限。
日志记录:行为过滤器可以用于记录应用程序的日志,例如在请求到达控制器或操作时记录请求和响应的信息。
异常处理:异常过滤器可以用于捕获和处理应用程序中的异常,例如在操作执行时发生错误时返回自定义错误消息。
缓存:资源过滤器可以用于实现缓存逻辑,例如在操作执行前从缓存中获取数据或将数据添加到缓存中。
性能优化:行为过滤器可以用于优化应用程序的性能,例如在请求到达控制器或操作之前检查请求参数的有效性,以避免不必要的操作。
.NET Core 依赖注入生命周期?
(1) Singleton单例模式:单例对象对于每个对象、每个请求都是一样的,对于不同的客户端、不同的请求可以说是一样的。
(2) Transient 瞬态模式:Transient对象总是不同的,每次都会创建一个新的实例,无论是同一个请求(同一个请求中的不同服务)还是同一个客户端。
(3) Scoped作用域模式:作用域对象在一个客户端请求中相同,但在多个客户端请求中不同。
ASP.NET Core Filter 注册方式有哪几种?它们的有效范围
- 方法注册:只对方法生效;
- 控制器注册:只对控制器中的方法生效;
- 全局注册:对整个项目生效;
简述.NET CORE中IOC生命周期?
Transient
(瞬间的):每次使用(获取这个服务的时候)时都会创建新的服务,适合轻量级的服务。Scoped
(作用域的):在同一次请求中只存在一次的服务。Singleton
(唯一的/单例的):全局只创建一次的服务,第一次被请求的时候被创建,然后就一直使用同一个。
ASP.NET Core 中 AOP 是通过什么来支持的?分别有哪些?
AOP 是通过 Filter 来支持的,分别有 IResourceFilter、AuthorizeFilter、ActionFilter、ExceptionFilter、ResultFilter。
IoC控制反转是什么?
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。
通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
MVVM视图模型?
MVVM
全称Model-View-ViewModel
是基于MVC
体系结构模式的改进,MVVM
就是MVC
模式中的View
的状态和行为抽象化,将视图UI
和业务逻辑分开,
更清楚地将用户界面UI
的开发与应用程序中业务逻辑和行为的开发区分开来
如何保证token的安全?
- Token授权机制
并将Token-UserId以键值对的形式存放在缓存服务器中。
- 时间戳超时机制
- 签名机制
将 Token 和 时间戳 加上其他请求参数再用MD5或SHA-1算法(可根据情况加点盐)加密,加密后的数据就是本次请求的签名sign,
服务端接收到请求后以同样的算法得到签名,并跟当前的签名进行比对,如果不一样,说明参数被更改过,直接返回错误标识。
签名机制保证了数据不会被篡改。
listview 、listbox区别==》
- 显示方式不同:listview支持多列视图,可以以表格形式展示,每个 单元格可以设置不同的属性;listbox只能显示一列数据。
- 选择方式不同:listview可选择一个选项,也可以选中多个选项,同时支持拖拽选中多个选项;listbox不支持拖拽选中选项。
- 数据操作不同:listview可通过代码动态添加、删除、修改列表项,同时支持在列表中添加图片、按钮、复选框等控件;而listbox只支持通过代码动态添加、删除、修改列表项。
- 使用场景不同:listview适用于显示多列数据、需要显示更丰富样式的列表需求。而listbox适用于显示单列简单数据的情况。
- 性能差异:和listbox相比listview支持更多的功能,因此其消耗的资源更多,因此在使用listview时需要注意性能问题。
winfrom wpf区别==》
- winfrom采用代码后置、前后端代码不分离,而wpf则采用基于xaml声明式前后端分离的方式,更易于维护,相比耦合度更低
- winfrom采用基于窗体控件模型、事件驱动的开发模式,而wpf则多用于mvvm模式
- winfrom比wpf更早面世,相比winfrom的学习成本wpf则需要更多的时间投入
- winfrom的布局方式基于像素级别,需开发人员进行手动调整,而wpf的布局方式更加灵活、强大--更适用于复杂布局
- 从界面出发:winfrom对于样式的应用比较难以操作,而wpf则提供了强大的自定义样式,同时对于数据的操作wpf支持依赖项属性、通知项属性高效实现数据的双向绑定等
- 性能层面winfrom则要比wpf好一些
wpf中什么是 DataContext?其作用是什么?
- wpf中,datacontext表示界面元素的数据上下文,每个wpf控件都有一个datacontext属性
- 用于数据绑定--通过将数据与界面元素的datacontext绑定,可实现数据与界面的分离,使界面元素能够自动显示和更新数据的变化。
1.Debug.WriteLine、Trace.WriteLine
//WriteLine Write Print
Debug.WriteLine("debug调试模式下--在跟踪窗口--输出指定内容:",message);
//Trace.Write
Trace.WriteLine("debug replease模式--在跟踪窗口--下输出指定内容", message);
Debug.write()用于调试模式下在输出窗口,输出调试信息
Trace.Write()则可在调试和replease模式下同时在输出窗口,输出调试信息
注:
Debug会产生pdb文件,release不会。
Debug用于开发时的调试,不能要于部署。
Release用于部署.debug编译一些特殊代码,比如#IFDEBUG Debug.Write等,而Release则会将那些特殊标记省略
2.params:https://learn.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/w5zay9db(v=vs.100)
params 关键字可以指定采用数目可变的参数的方法参数。
可以发送参数声明中所指定类型的逗号分隔的参数列表或指定类型的参数数组。 还可以不发送参数。
在方法声明中的 params 关键字之后不允许任何其他参数(该参数必须是最后一个参数),并且在方法声明中只允许一个 params 关键字。
1 public class MyClass
2 {
3 public static void UseParams(params int[] list)
4 {
5 for (int i = 0; i < list.Length; i++)
6 {
7 Console.Write(list[i] + " ");
8 }
9 Console.WriteLine();
10 }
11
12 public static void UseParams2(params object[] list)
13 {
14 for (int i = 0; i < list.Length; i++)
15 {
16 Console.Write(list[i] + " ");
17 }
18 Console.WriteLine();
19 }
20
21 static void Main()
22 {
23 // You can send a comma-separated list of arguments of the
24 // specified type.
25 UseParams(1, 2, 3, 4);
26 UseParams2(1, 'a', "test");
27
28 // A params parameter accepts zero or more arguments.
29 // The following calling statement displays only a blank line.
30 UseParams2();
31
32 // An array argument can be passed, as long as the array
33 // type matches the parameter type of the method being called.
34 int[] myIntArray = { 5, 6, 7, 8, 9 };
35 UseParams(myIntArray);
36
37 object[] myObjArray = { 2, 'b', "test", "again" };
38 UseParams2(myObjArray);
39
40 // The following call causes a compiler error because the object
41 // array cannot be converted into an integer array.
42 //UseParams(myObjArray);
43
44 // The following call does not cause an error, but the entire
45 // integer array becomes the first element of the params array.
46 UseParams2(myIntArray);
47 }
48 }
49 /*
50 Output:
51 1 2 3 4
52 1 a test
53
54 5 6 7 8 9
55 2 b test again
56 System.Int32[]
57 */
3.delegate是引用类型还是值类型?enum、int[]和string呢(难度系数40%)?
答案:delegate引用类型,enum值类型,int[]引用类型,string引用类型。
虚方法==》虚方法的使用,一般应用于面向对象的多态场景。
使用vitural关键字;
虚方法的定义可以有方法体,其派生类可以重新虚方法,也可以不重写,重写使用override
抽象类abstract
抽象类中不一定有抽象方法
有抽象方法的一定是抽象类
抽象类用于声明抽象方法,可以有属性,但不能有构造,不能使用new实例化
抽象类的派生类必须重写抽象类的抽象方法
接口interface:一般定义采用I开头
用于方法的声明,不能有方法体,不能有修饰符
全部的方法都是抽象的,一个类可以继承多个接口;
继承接口的类,必须实现定义的所有方法
密封类sealed
密封类不能被继承
重写与重载
重写是两个之间的关系,是子类和父类之间方法的重写关系
重载是一个类内的内部关系,即方法名称相同,参数个数或参数类型不同
数组没有Length()方法,有length属性
Array数组使用sort()排序;
ArrayList使用orderby\thenby\orderbydesc...排序
引用类型+值类型
装箱== 值类型到引用类型
拆卸==引用类型到值类型
常见值类型:常用普通数据类型,例如:int、double、char、bool、long、short、结构、枚举...
常见引用类型:string、object、类、接口
类、结构==》类为引用类型;结构为值类型;
类可以有构造,默认有无参构造;可通过new实例化——结构不能有构造,不能new
try catch finally ,finally在 return 后执行
MVVM--Model-view-viewmodel。
其本质就是MVC 模型、视图、控制器的改进版本
常用的如prism
在wpf应用中相关的一些技术或方法如,路由事件绑定、通知项属性、命令、通过dataContext上下文使模型、视图、控制器建立联系。
Using语句的作用==》
- 导入命名空间
- 类型别名
- try finally语法糖,避免手动释放dispose释放资源
第一问:C#中变量类型分为哪两种?
值类型和引用类型,值类型变量自身存储数据,引用类型存储的是实际数据的引用,通过引用找到实际的数据。
第二问:Class和Struct的区别?
Class为引用类型,可以被new实例化,默认private,存储实际的引用;
Struct为值类型,不能new示例,默认public,值类型自身存储数据数据。
第三问:C#中类的修饰符和类成员的修饰符有哪些?
C#中可以修饰类的修饰符为:public、internal、sealed、abstract
C#中不能修饰类的修饰符为:private和protected
C#中成员的修饰符为:public、internal、protected、private
public:完全公开,没有访问限制。
internal:可以应用于当前应用程序以及类库。
protected:在当前类和子类中可以使用。
private:只有在当前类中可以使用。
sealed:密封类,不能被其他类型继承。
abstract:抽象类,不能创建实例。
第四问:面向对象的三个特征(特点)是什么?
封装:把对象的属性或者行为封装起来,类似于一个类。
继承:子类可以继承父类。
多态:父类可以应用于子类,子类可以去使用父类的一些特征方法。
第五问:面向对象和面向过程的区别?
面向对象:把问题分解成多个对象,强调的是解决问题行为标准(方式)
面向过程:分析问题并解决问题的步骤,强调的是解决问题的步骤。
第六问:什么是装箱和拆箱?
装箱:从值类型转换到引用类型。
拆箱:从引用类型到值类型的转换。
第七问:什么事IOC?
控制反转,是一种思想(设计模式)而不是一种技术实现。
控制:拥有创建对象的权利。
反转:把控制权交给IOC容器。
优点: 1、对象之间的耦合度或依赖度降低。
2、资源容易管理
传统模式下:在一个类中需要new关键字去实例化另一个类。
IOC设计模式:不需要new去创建对象,直接从IOC容器中获取。
第八问:什么事OOP?
面向对象编程
提取共有的属性和方法,形成一个父类。
第九问:什么事AOP?
面向切面的编程,在不改变原有的业务逻辑情况下,横切逻辑代码,解耦合代码,避免横切代码重复。
切:指的是横向逻辑,就是保证原有的业务逻辑代码不变,操作横切逻辑代码,所以就是面相横切编程。
面:横切代码影响的是很多方法,每个方法如同一个点,很多点就形成面。
应用场景:事务控制,权限效验、日志信息等。
多个方法的相同位置出现重复代码。
第十问:什么事DI?
依赖注入:构造注入、方法注入、属性注入
DI是IOC设计思想的实现方式
一个类去引用另外一个类,就会产生依赖。
优点:如果添加另一个类,不需要修改之前代码,只要修改注入的地方将实现类进行替换。实例化接口的时候,不用手动new来狗仔实现类,交给IOC容器进行构建。
实现了解耦
DIP:依赖注入倒置原则:依赖于抽象,不依赖预聚体,高层模块不依赖于低层模块,它们依赖于抽象。
代码中如何实现多态
接口实现 继承父类重写方法 同一类中进行方法重载
描述sealed修饰符的使用
sealed修饰符用于修饰类、实例方法和属性。sealed用于修饰类时,该类无法被继承,所以该类也被称为密封类。而abstract类(抽象类)必须被继承才有意义,所以,sealed修饰符和abstract修饰符是互相排斥的,无法共存。密封方法会重写基类的方法,sealed用于修饰实例被重写的虚方法或虚属性时,表示该方法或属性无法再被重写。
IOC/DI/AOP
1.IOC即控制反转,是一种设计思想,在之前的项目中,当我们需要一个对象时,需要new一个对象,而IOC的设计思想是我们将需要的对象注入到一个容器中,就会获得我们所需要的资源 。
2.DI是依赖注入,我们将需要的对象注入到容器中,获取所需要的资源。
3.AOP 在运行时,动态地将代码切入到指定方法、指定位置上的编程思想就是面向切面的编程。
使用:先创建一个类继承自IAsyncActionFilter、在startup中添加 依赖、然后添加标签
进程和线程的关系:
1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
2.资源分配给进程,同一进程的所有线程共享该进程的所有资源。
3.线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
线程与进程的区别:
1.调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2.并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3.拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。
类和结构的区别?
结构和类具有大体的语法,但是结构受到的限制比类要多。结构不能申明有默认的构造函数,为结构的副本是又编译器创建和销毁的,所以不需要默认的构造函数和析构函数。结构是值类型,所以对结构变量所做的改变不会影响其的原值,而类是引用类型,改变其变量的值会改变其原值。申明结构用Struck 关键字,申明类用 class 关键字,向方法传递结构是时是通过值传递的,而不是通过引用。与类不同,结构的实例化可以不使用New关键字。类可以实现接口。
值类型和引用类型的区别?
值类型是存放在栈中的,改变其值,不改变变量原有的值,而引用类型的值是存放在堆中的,其引用的地址是存放在栈中的,改变其值也就改变了变量原有的值。值类型不允许包含null值,然而可空类型可以将null赋值给值类型l。
foreach 和 for 循环从性能角度的区别。
对于for循环就是调用get(i)取得元素,而对于foreach是通过iterator实现的遍历,
对于数组来说,for和foreach循环效率差不多,但是对于链表来说,for循环效率明显比foreach低。
抽象方法和虚方法的区别
抽象方法一定是虚方法,虚方法未必是抽象方法。虚方法是指可以被继承类重写的方法,而抽象方法是指,基类是抽象类,没有实现它,因此必须被继承类重写的方法。
抽象与接口:
构造器Constructor是否可以被继承?是否可以被Override?
Constructor不可以被继承,因此不能被重写(Overriding),但可以被重载(Overloading).
Const和ReadOnly?
Const用来申明编程时申明常量,是静态常量,不可被static修饰,ReadOnly用来申明运行时常量,是动态常量,使用时才会初始化。
HTTP状态码:
200:请求被正常处理
400:请求报文语法有误,服务器无法识别
403:请求的对应资源禁止被访问
404:服务器无法找到对应资源
500:服务器内部错误000
503:服务器正忙
.Net Core 3.0和2.0 相比,加了哪些东西, net5?
只保留了一些必要的包,去除了其他(如EF,JSON.NET),删除很多过时的API,授权有了很大改变,SigfnalR修改,MVC,Rezor修改。
.Net 5 Framework,Core核心的结合,blaze,socket, .Net Xamarin 趋于统一
.net core和.net framework的区别
- 跨平台,它可以运行在三大操作系统上面,windows, Linux和MAC。
- 对架构本身安装没有依赖,因为所有的依赖都跟程序本身在一起。
- 更高的性能和处理能力,支持docker
- 内置依赖注入,日志处理
- 还有HTTP请求管道
Singleton
单例模式,服务在第一次请求时被创建,其后的每次请求都沿用这个已创建的服务。我们不用再自己写单例了。
Scoped
作用域模式,服务在每次请求时被创建,整个请求过程中都贯穿使用这个创建的服务。比如Web页面的一次请求。
Transient
瞬态模式,服务在每次请求时被创建,它最好被用于轻量级无状态服务。
如果一个系统出现性能瓶颈,让你来处理的话,说说你的性能优化计划。
硬件上,加服务器配置,固态内存等,多台服务器集群负载均衡,或者业务拆分(分布式)。
设计上,可以使用读写分离、分库分表、Redis、Elasticsearch、MQ排队
代码上,简化代码、冗余字段、文件压缩、图片压缩、前端体验(loading动画、伪进度条)。
集群、分布式和微服务的区别
分布式:一个业务拆分成多个子业务,子业务分别部署在不同的服务器上。
集群:同一个业务,部署在多个服务器上。
微服务:就是很小的服务,小到一个功能就是一个服务,可以单独部署运行。
微服务和分布式之间的区别就是微服务的应用不一定分散在不同的服务器上,也可以在同一个服务器上多个服务。
分布式系统解决数据一致性问题
CAP 是指在一个分布式系统下, 包含三个要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),并且三者不可得兼。
2PC(两阶段提交)、3PC(三阶段提交): 省略
TCC方案:
每一次事务都要定义三个操作,try-confirm-cancel。而且TCC对业务的侵入性比较大,每个业务都要写相应得到撤销方法。
最大努力通知:
其实也算是一种最终一致性的方案,主要是当A系统执行完本地事务后,发送消息给MQ,然后去让B系统执行事务操作,如果B系统执行完成了,就消费消息,若B系统执行失败了,则执行重试,重试多次直到成功。若达到一定次数后还没成功就只能人工干预了。
C#中的委托是什么?事件是不是一种委托?
委托的本质是一个密封类。这个类继承自System.MultiDelegate,其再继承自System.Delegate。这个密封类包括三个核心函数,Invoke方法赋予其同步访问的能力,BeginInvoke,EndInvoke赋予其异步访问的能力。委托他可以把一个方法作为参数代入另一个方法,委托可以理解为指向一个函数的引用。
事件是一种特殊的委托,是委托的一个实例,事件的内部是用委托实现的,事件内部就是一个private的委托和add、remove两个方法
delegate <函数返回类型> <委托名> (<函数参数>)
为什么要使用委托?
逻辑解耦,保持程序稳定,代码复用,保证项目的规范性。
怎么使用事件?
声明委托 声明事件 事件注册
为什么要使用扩展方法?
和抽象类比较,需要扩展密封类的方法时,我们可以使用到扩展方法。在扩展接口的时候。需要扩展,要继承实现接口(会强制要求实现接口下的所有方法)。
简述 private、 protected、 public、internal 修饰符的访问权限。
private : 私有成员, 在类的内部才可以访问。 类成员默认
protected: 保护成员,该类内部和继承类中可以访问。
public: 公共成员,完全公开,没有访问限制。
internal:在同一命名空间内可以访问。 类默认
internal protected:在所属程序集或当前类的子类中可以访问。
描述类和对象的区别
类(即class)指一类事物,对象(即object)指属于这一类事物的实体。类定义了对象的相关数据和方法,类通过构造函数生成对象,对象实现了类的定义,且拥有具体的数据。
代码中如何实现多态
接口实现 继承父类重写方法 同一类中进行方法重载
描述sealed修饰符的使用
sealed修饰符用于修饰类、实例方法和属性。sealed用于修饰类时,该类无法被继承,所以该类也被称为密封类。而abstract类(抽象类)必须被继承才有意义,所以,sealed修饰符和abstract修饰符是互相排斥的,无法共存。密封方法会重写基类的方法,sealed用于修饰实例被重写的虚方法或虚属性时,表示该方法或属性无法再被重写。
IOC/DI/AOP
1.IOC即控制反转,是一种设计思想,在之前的项目中,当我们需要一个对象时,需要new一个对象,而IOC的设计思想是我们将需要的对象注入到一个容器中,就会获得我们所需要的资源 。
2.DI是依赖注入,我们将需要的对象注入到容器中,获取所需要的资源。
3.AOP 在运行时,动态地将代码切入到指定方法、指定位置上的编程思想就是面向切面的编程。
使用:先创建一个类继承自IAsyncActionFilter、在startup中添加 依赖、然后添加标签
C#类成员一般初始化顺序:
子类静态字段\子类静态构造\子类实例字段\父类静态字段\父类静态构造\父类实例字段\父类实例构造\子类实例构造
进程和线程的关系:
1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
2.资源分配给进程,同一进程的所有线程共享该进程的所有资源。
3.线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
线程与进程的区别:
1.调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2.并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3.拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。
类和结构的区别?
结构和类具有大体的语法,但是结构受到的限制比类要多。结构不能申明有默认的构造函数,为结构的副本是又编译器创建和销毁的,所以不需要默认的构造函数和析构函数。结构是值类型,所以对结构变量所做的改变不会影响其的原值,而类是引用类型,改变其变量的值会改变其原值。申明结构用Struck 关键字,申明类用 class 关键字,向方法传递结构是时是通过值传递的,而不是通过引用。与类不同,结构的实例化可以不使用New关键字。类可以实现接口。
值类型和引用类型的区别?
值类型是存放在栈中的,改变其值,不改变变量原有的值,而引用类型的值是存放在堆中的,其引用的地址是存放在栈中的,改变其值也就改变了变量原有的值。值类型不允许包含null值,然而可空类型可以将null赋值给值类型l。
foreach 和 for 循环从性能角度的区别。
对于for循环就是调用get(i)取得元素,而对于foreach是通过iterator实现的遍历,
对于数组来说,for和foreach循环效率差不多,但是对于链表来说,for循环效率明显比foreach低。
C# IQueryable和IEnumerable的区别
在Queryable中,参数接收的是一个表达式类型Expression,返回IQueryable接口
在Enumerable中,参数接收的是一个谓词表达式Func<>,也就是一个委托
IEnumerable<T> 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable<T> 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。
抽象方法和虚方法的区别
抽象方法一定是虚方法,虚方法未必是抽象方法。虚方法是指可以被继承类重写的方法,而抽象方法是指,基类是抽象类,没有实现它,因此必须被继承类重写的方法。
为什么要是使用抽象?为什么要使用接口?
先用接口确定系统行为,然后用Mock类进行对接口的实现,在这个时候根本就没抽象类什么事情。接口表达一个契约,表达系统和系统间的协议,属于业务层。
很多具体类,出现很多重复代码,将其提炼出抽象类简化代码。而抽象类不过是提取公因式,简化代码而已。
构造器Constructor是否可以被继承?是否可以被Override?
Constructor不可以被继承,因此不能被重写(Overriding),但可以被重载(Overloading).
Const和ReadOnly?
Const用来申明编程时申明常量,是静态常量,不可被static修饰,ReadOnly用来申明运行时常量,是动态常量,使用时才会初始化。
数据库与缓存
索引原理及使用
底层是经过优化的B+树,索引在频繁查询的、需要排序的字段上使用。索引需要占用物理空间,当对表进行增、删、改、的时候索引也要动态维护,这样就降低了数据的维护速度。
创建索引:CREATE INDEX index_name ON table_name (column_name) ;
什么情况下设置了索引但无法使用
以“%”开头的LIKE语句,模糊匹配,OR语句前后使用索引
简单描述mysql中,索引,主键,唯一索引,联合索引的区别,对数据库的性能有什么影响(从读写两方面)
普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。
普通索引允许被索引的数据列包含重复的值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。也就是说, 唯一索引可以保证数据记录的唯一性。
主键,是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字PRIMARY KEY 来创建。
索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引,这就是联合索引。
索引可以极大的提高数据的查询速度,但是会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要操作索引文件。
聚集索引与非聚集索引的区别
聚集索引一个表只能有一个,key值应该是唯一的,而非聚集索引一个表可以存在多个
聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续
谈谈数据库分库分表的方式。
1.垂直切分:
根据业务的不同,将原先拥有很多字段的表拆分为两个或者多个表,这样的代价我个人觉得很大,原来对这应这个表的关系,开始细分,需要一定的重构,而且随着数据量的增多,极有可能还要增加水平切分;
2.水平切分:
数据库/数据表结构相同,将数据分散在多个数据库/表中;
3.取模分库:
一般的取模分库分表是就是将id mod n,然后放入数据库中,这样能够使数据分散,不会有热点的问题,那么,剩下的是,在扩容的时候,是否会有数据迁移的问题,一般的扩容,当然是会有数据迁移的。
预防死锁:
资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)
少用大事务,拆分小事务
数据库查询优化
- 加合理的索引,注意where后面的字段顺序,不允许null,%不能在左边。
- 读写分离,log同步。
- 拆分复杂的查询语句,少用子查询。
- Redis、elasticsearch
- 太复杂,quartz或者存储过程定时查询,查询结果放在结果表中,直接拿结果表的数据
- 冗余字段、
- 加内存加硬件
如何解决Redis缓存与MySQL的数据一致性问题
- 延时双删,先删缓存,再写数据库,休眠一段时间后,再删缓存。
- 异步消息梳理,读redis=>写mysql=>更新redis=>mq=>redis服务器订阅更新数据,然后同步更新
数据库中的隔离级别
脏读:是指一个事务读取了未提交事务执行过程中的数据。
不可重复读:A事务中第一次和第二次读取到的数据不一致,在A事务两次读取数据之间,B事务对数据进行了修改并且提交了,然后A事务第二次读取到的数据就是B事务修改之后的数据,导致A事务第一次和第二次读取到的数据不一致,这就叫做不可重复读。
幻读:它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
脏读 |
不可重复读 |
幻读 |
|
Read uncommitted |
√ |
√ |
√ |
Read committed--Sql Server , Oracle |
× |
√ |
√ |
Repeatable read--MySQL |
× |
× |
√ |
Serializable |
× |
× |
× |
事务特点;原子性、一致性、隔离性、持久性。
Redis
Redis 支持持久化,所以 Redis 不仅仅可以用作缓存,也可以用作 NoSQL 数据库。
相比 MC,Redis支持多种数据格式,例如 list、set、sorted set、hash 等,还有Incr decr自增自减、expire过期时间等功能。
Redis 提供主从同步机制,以及 Cluster 集群部署能力,能够提供高可用服务。
持久化:RDB 是把内存中的数据集以快照形式每隔一段时间写入磁盘,AOF 是以文本日志的形式记录 Redis 处理的每一个写入或删除操作。
缓存穿透
用户频繁请求不存在的数据接口,缓存里找不到,这时会有大量请求穿透缓存访问到 DB。
使用BloomFilter过滤器,BloomFilter 的特点是存在性检测,如果 BloomFilter 中不存在,那么数据一定不存在;如果 BloomFilter 中存在,实际数据也有可能会不存在。
缓存击穿
缓存击穿,就是某个热点数据失效时,大量针对这个数据的请求会穿透到数据源。
可以使用互斥锁更新
设置热点数据永远不过期。
缓存雪崩
缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
设置热点数据永远不过期。
框架与设计
.Net Core 3.0和2.0 相比,加了哪些东西, net5?
只保留了一些必要的包,去除了其他(如EF,JSON.NET),删除很多过时的API,授权有了很大改变,SigfnalR修改,MVC,Rezor修改。
.Net 5 Framework,Core核心的结合,blaze,socket, .Net Xamarin 趋于统一
.net core和.net framework的区别
- 跨平台,它可以运行在三大操作系统上面,windows, Linux和MAC。
- 对架构本身安装没有依赖,因为所有的依赖都跟程序本身在一起。
- 更高的性能和处理能力,支持docker
- 内置依赖注入,日志处理
- 还有HTTP请求管道
Singleton
单例模式,服务在第一次请求时被创建,其后的每次请求都沿用这个已创建的服务。我们不用再自己写单例了。
Scoped
作用域模式,服务在每次请求时被创建,整个请求过程中都贯穿使用这个创建的服务。比如Web页面的一次请求。
Transient
瞬态模式,服务在每次请求时被创建,它最好被用于轻量级无状态服务。
如果一个系统出现性能瓶颈,让你来处理的话,说说你的性能优化计划。
硬件上,加服务器配置,固态内存等,多台服务器集群负载均衡,或者业务拆分(分布式)。
设计上,可以使用读写分离、分库分表、Redis、Elasticsearch、MQ排队
代码上,简化代码、冗余字段、文件压缩、图片压缩、前端体验(loading动画、伪进度条)。
集群、分布式和微服务的区别
分布式:一个业务拆分成多个子业务,子业务分别部署在不同的服务器上。
集群:同一个业务,部署在多个服务器上。
微服务:就是很小的服务,小到一个功能就是一个服务,可以单独部署运行。
微服务和分布式之间的区别就是微服务的应用不一定分散在不同的服务器上,也可以在同一个服务器上多个服务。
分布式系统解决数据一致性问题
CAP 是指在一个分布式系统下, 包含三个要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),并且三者不可得兼。
2PC(两阶段提交)、3PC(三阶段提交): 省略
TCC方案:
每一次事务都要定义三个操作,try-confirm-cancel。而且TCC对业务的侵入性比较大,每个业务都要写相应得到撤销方法。
最大努力通知:
其实也算是一种最终一致性的方案,主要是当A系统执行完本地事务后,发送消息给MQ,然后去让B系统执行事务操作,如果B系统执行完成了,就消费消息,若B系统执行失败了,则执行重试,重试多次直到成功。若达到一定次数后还没成功就只能人工干预了。