好奇害死猫
一直觉得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/
目前计划
后续待定。。。。。。
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.
private const string ProjectName = "Learn.WebApi";
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
#region Swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = ProjectName,
Version = "v1",
Description = $"{ProjectName} HTTP API ",
TermsOfService = new Uri("https://github.com/dingshuanglei"),
Contact = new OpenApiContact { Name = "丁双磊", Email = "shuangleiding@163.com", Url = new Uri("https://github.com/dingshuanglei") }
});
var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
var xmlPath = Path.Combine(basePath, $"{ProjectName}.xml");
c.IncludeXmlComments(xmlPath, true);
var modelXmlPath = Path.Combine(basePath, "Learn.Model.xml");
c.IncludeXmlComments(modelXmlPath, true);
// Add security definitions
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Description = "Please enter into field the word 'Bearer' followed by a space and the JWT value",
Name = "token",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference()
{
Id = "Bearer",
Type = ReferenceType.SecurityScheme
}
}, Array.Empty<string>()
}
});
});
#endregion
#region db init
InitDbTable.InitTable();
#endregion
services.AddControllers();
}
Startup-》Configure 方法中启用Swagger和静态文件UseStaticFiles。
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
#region Swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", $"v1");
c.RoutePrefix = string.Empty;
});
#endregion
app.UseAuthorization();
//使用静态文件
app.UseStaticFiles();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Program-》CreateHostBuilder 方法中将默认ServiceProviderFactory指定为AutofacServiceProviderFactory。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
//将默认ServiceProviderFactory指定为AutofacServiceProviderFactory
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Autofac Ioc
Startup-》添加ConfigureContainer方法注入需要Ioc管理的类及类库,当前项目中使用的注入没有特殊的需求,普通的注入业务层和数据访问层类库,也可以根据您自身项目的需要指定注入的生命周期、单接口多实现等等。
/// <summary>
/// autofac ioc
/// </summary>
/// <param name="builder"></param>
public void ConfigureContainer(ContainerBuilder builder)
{
//使用单例模式
//builder.RegisterType<Test>().As<ITest>().SingleInstance().PropertiesAutowired();
//单接口多实现
//builder.RegisterType<TestOne>().Named<ITest>(nameof(TestOne));
//builder.RegisterType<TestTwo>().Named<ITest>(nameof(TestTwo));
Assembly[] assembliesService = new Assembly[] { Assembly.Load("Learn.Service") };
builder.RegisterAssemblyTypes(assembliesService).Where(type => !type.IsAbstract && typeof(IocService).IsAssignableFrom(type)).AsImplementedInterfaces().PropertiesAutowired();
Assembly[] assembliesRepository = new Assembly[] { Assembly.Load("Learn.Repository") };
builder.RegisterAssemblyTypes(assembliesRepository).Where(type => !type.IsAbstract).AsImplementedInterfaces().PropertiesAutowired();
}
代码下载地址: SourceCode 作者水平有限欢迎园友纠正错误及不恰当之处,予以及时修正以免误导他人!