手擼ORM淺談ORM框架之基礎篇

好奇害死貓

一直覺得ORM框架好用、功能強大集眾多優點於一身,當然ORM並非完美無缺,任何事物優缺點並存!我曾一度認為以為使用了ORM框架根本不需要關注Sql語句如何執行的,更不用關心優化的問題!!! 隨着髮際線後移高亮意識到優秀程序員寫的優秀的ORM框架會做一些Sql優化,Sql優化不是一成不變的,ORM框架不會根據項目業務場景等主動優化Sql語句。如果ORM真的強大的到開發人員不需要關注Sql,會針對當前項目情況做出相對應很好的優化,必然會增加ORM框架的體積、帶來性能等相關問題。知己知彼,百戰不殆。一直想探索ORM原理,為什麼調用ORM Add或Insert方法都可以把實體寫入到數據庫???由於好奇之心我準備寫一個ORM系列隨筆,淺談對ORM的理解,作者水平有限歡迎園友糾正錯誤及不恰當之處。

千里之行始於足下


ORM對象關係映射(英語:Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序設計技術,用於實現面向對象編程語言里不同類型系統的數據之間的轉換。

技術棧: .NET Core 3.1 + MySql + Autofac + Swagger

官方地址傳送:

微軟NET Core 3.1: 中文//docs.microsoft.com/zh-cn/dotnet/   英文//docs.microsoft.com/en-us/dotnet/

MySql 8.x 文檔: //dev.mysql.com/doc/

Autofac文檔: 中文//autofaccn.readthedocs.io/zh/latest/   英文//autofaccn.readthedocs.io/en/latest/

Swagger文檔: //swagger.io/docs/

目前計劃

手擼ORM淺談ORM框架之基礎篇

手擼ORM淺談ORM框架之Add篇

手擼ORM淺談ORM框架之Update篇

手擼ORM淺談ORM框架之Delete篇

手擼ORM淺談ORM框架之Query篇

後續待定。。。。。。

MySql 8.x 坎(待解決)


 //Grant all privileges on learndb.* to ‘learn_user@’@’%’

//> 1410 – You are not allowed to create a user with GRANT
//Sql = @”CREATE DATABASE IF NOT EXISTS learndb;”

因此,權限需要先手動授予: 服務器權限-》Create

注:遇到的項目中一般都是數據庫優先或者使用的EntityFramework來創建數據庫,MySql8.x命令授權給用戶不太熟練。

 新風尚WebApi

.NET Framework使用靜態資源除了保護文件夾可以直接添加需要的靜態資源文件夾即可;.NET Core使用靜態文件需要在Startup-》Configure 方法中啟用靜態文件UseStaticFiles並且文件夾的名稱:wwwroot,否則禁止訪問靜態資源。WebApi添加wwwroot文件夾存放靜態資源,.Net Core中需要手動添加swagger靜態樣式資源,下載地址 : swagger-ui ,您也可以使用項目中的wwwroot裏面的樣式。

Api神器Swagger

Startup-》ConfigureServices 方法中添加Swagger 文檔doc、xml、security等信息。新版本Swashbuckle.AspNetCore.Swagger有一些改動,例如SwaggerDoc-》OpenApiInfo的屬性TermsOfService由String修改為Uri,在對TermsOfService賦值時如果非Uri或String無法轉換正確的Uri項目Debug時會拋出下面異常。

System.UriFormatException
HResult=0x80131537
Message=Invalid URI: The format of the URI could not be determined.

 1 private const string ProjectName = "Learn.WebApi";
 2 
 3 // This method gets called by the runtime. Use this method to add services to the container.
 4 public void ConfigureServices(IServiceCollection services)
 5 {
 6     #region Swagger
 7 
 8     services.AddSwaggerGen(c =>
 9     {
10         c.SwaggerDoc("v1", new OpenApiInfo
11         {
12             Title = ProjectName,
13             Version = "v1",
14             Description = $"{ProjectName} HTTP API ",
15             TermsOfService = new Uri("//github.com/dingshuanglei"),
16             Contact = new OpenApiContact { Name = "丁雙磊", Email = "[email protected]", Url = new Uri("//github.com/dingshuanglei") }
17         });
18 
19         var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
20         var xmlPath = Path.Combine(basePath, $"{ProjectName}.xml");
21         c.IncludeXmlComments(xmlPath, true);
22         var modelXmlPath = Path.Combine(basePath, "Learn.Model.xml");
23         c.IncludeXmlComments(modelXmlPath, true);
24 
25         // Add security definitions
26         c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
27         {
28             Description = "Please enter into field the word 'Bearer' followed by a space and the JWT value",
29             Name = "token",
30             In = ParameterLocation.Header,
31             Type = SecuritySchemeType.ApiKey,
32         });
33         c.AddSecurityRequirement(new OpenApiSecurityRequirement
34         {
35             {
36                 new OpenApiSecurityScheme
37                 {
38                     Reference = new OpenApiReference()
39                     {
40                         Id = "Bearer",
41                         Type = ReferenceType.SecurityScheme
42                     }
43                 }, Array.Empty<string>()
44             }
45         });
46     });
47 
48     #endregion
49 
50     #region db init
51 
52     InitDbTable.InitTable();
53     
54     #endregion
55 
56     services.AddControllers();
57 }

View Code

Startup-》Configure 方法中啟用Swagger和靜態文件UseStaticFiles。

 1 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
 2 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 3 {
 4     if (env.IsDevelopment())
 5     {
 6         app.UseDeveloperExceptionPage();
 7     }
 8 
 9     app.UseRouting();
10 
11     #region Swagger
12     app.UseSwagger();
13     app.UseSwaggerUI(c =>
14     {
15         c.SwaggerEndpoint("/swagger/v1/swagger.json", $"v1");
16         c.RoutePrefix = string.Empty;
17     });
18     #endregion
19 
20     app.UseAuthorization();
21 
22     //使用靜態文件
23     app.UseStaticFiles();
24 
25     app.UseEndpoints(endpoints =>
26     {
27         endpoints.MapControllers();
28     });
29 }

View Code

Program-》CreateHostBuilder 方法中將默認ServiceProviderFactory指定為AutofacServiceProviderFactory。

1 public static IHostBuilder CreateHostBuilder(string[] args) =>
2    Host.CreateDefaultBuilder(args)
3        //將默認ServiceProviderFactory指定為AutofacServiceProviderFactory
4        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
5        .ConfigureWebHostDefaults(webBuilder =>
6        {
7            webBuilder.UseStartup<Startup>();
8        });

View Code

Autofac Ioc

Startup-》添加ConfigureContainer方法注入需要Ioc管理的類及類庫,當前項目中使用的注入沒有特殊的需求,普通的注入業務層和數據訪問層類庫,也可以根據您自身項目的需要指定注入的生命周期、單接口多實現等等。

 1 /// <summary>
 2 /// autofac ioc
 3 /// </summary>
 4 /// <param name="builder"></param>
 5 public void ConfigureContainer(ContainerBuilder builder)
 6 {
 7     //使用單例模式
 8     //builder.RegisterType<Test>().As<ITest>().SingleInstance().PropertiesAutowired();
 9 
10     //單接口多實現
11     //builder.RegisterType<TestOne>().Named<ITest>(nameof(TestOne));
12     //builder.RegisterType<TestTwo>().Named<ITest>(nameof(TestTwo));
13 
14     Assembly[] assembliesService = new Assembly[] { Assembly.Load("Learn.Service") };
15     builder.RegisterAssemblyTypes(assembliesService).Where(type => !type.IsAbstract && typeof(IocService).IsAssignableFrom(type)).AsImplementedInterfaces().PropertiesAutowired();
16 
17     Assembly[] assembliesRepository = new Assembly[] { Assembly.Load("Learn.Repository") };
18     builder.RegisterAssemblyTypes(assembliesRepository).Where(type => !type.IsAbstract).AsImplementedInterfaces().PropertiesAutowired();
19 }

View Code

代碼下載地址: SourceCode  作者水平有限歡迎園友糾正錯誤及不恰當之處,予以及時修正以免誤導他人!