好奇害死貓
一直覺得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: 中文https://docs.microsoft.com/zh-cn/dotnet/ 英文https://docs.microsoft.com/en-us/dotnet/
MySql 8.x 文件: https://dev.mysql.com/doc/
Autofac文件: 中文https://autofaccn.readthedocs.io/zh/latest/ 英文https://autofaccn.readthedocs.io/en/latest/
Swagger文件: https://swagger.io/docs/
目前計劃
手擼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("https://github.com/dingshuanglei"), 16 Contact = new OpenApiContact { Name = "丁雙磊", Email = "shuangleiding@163.com", Url = new Uri("https://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 }
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 }
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 });
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 }
程式碼下載地址: SourceCode 作者水平有限歡迎園友糾正錯誤及不恰當之處,予以及時修正以免誤導他人!