NET6App
介紹
.NET 6的CoreApp框架,用來學習.NET6的一些變動和新特性,使用EFCore,等一系列組件的運用,每個用單獨的檔案篇章記錄,持續更新檔案哦,
如果對您有幫助,點擊?Star?關注 ,感謝支持開源!
軟體架構
分為模型層,服務層,介面層來做測驗使用
0.如何使用IConfiguration、Environment
直接在builder后的主機中使用,
builder.Configuration;
builder.Environment
1.如何使用Swagger
.NET 6 自帶模板已經默認添加Swagger,直接使用即可,
builder.Services.AddSwaggerGen();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
2. 如何添加EFCore到.NET 6中
按照EFCore常規使用方法,申明表的Entity及Dbcontext后,在program.cs檔案中添加
builder.Services.AddDbContext<Service.DataContext>(opt => {
opt.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
});
即可在其他地方注入使用 DataContext
使用Sqlite資料庫,需要參考 Microsoft.EntityFrameworkCore.Sqlite,
并在添加服務時,改為
opt.UseSqlite(builder.Configuration.GetConnectionString("Default"));
包管理控制臺資料庫結構生成方法:
使用 add-migration 創建遷移
使用 update-database 更新資料結構
3.如何注入一個服務
builder.Services.AddScoped<UserIdentyService>();
4.如何定義全域的using參考
在根目錄下新建一個 cs檔案,比如Globalusing.cs,在里面添加你的全域參考,和常規參考不同的是,在using前面添加 global
global using Service;
global using Entity;
global using Entity.Dto;
5.如何使用Autofac
添加 Nuget 參考
Autofac.Extensions.DependencyInjection
program.cs檔案添加autofac的使用和注入配置
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
Assembly assembly = Assembly.Load("Service.dll");
builder.RegisterAssemblyTypes(assembly)
//.AsImplementedInterfaces()// 無介面的注入方式
.InstancePerDependency();
});
此時即可建構式注入使用,
6.如何使用Log4Net
添加參考
Microsoft.Extensions.Logging.Log4Net.AspNetCore
新建組態檔 log4net.config;
添加service配置
//注入Log4Net
builder.Services.AddLogging(cfg =>
{
//默認的組態檔路徑是在根目錄,且檔案名為log4net.config
//cfg.AddLog4Net();
//如果檔案路徑或名稱有變化,需要重新設定其路徑或名稱
//比如在專案根目錄下創建一個名為config的檔案夾,將log4net.config檔案移入其中,并改名為log4net.config
//則需要使用下面的代碼來進行配置
cfg.AddLog4Net(new Log4NetProviderOptions()
{
Log4NetConfigFileName = "config/log4net.config",
Watch = true
});
});
即可在需要的地方定義使用
_logger = LogManager.GetLogger(typeof(UserController));
7.如何使用全域例外過濾器
首先新建 GlobalExceptionFilter 全域例外過濾器,繼承于 ExceptionFilter ,用于接收處理拋出的例外
public class GlobalExceptionFilter : IExceptionFilter
{
readonly IWebHostEnvironment hostEnvironment;
readonly ILog logger;
public GlobalExceptionFilter(IWebHostEnvironment _hostEnvironment)
{
this.hostEnvironment = _hostEnvironment;
this.logger = LogManager.GetLogger(typeof(GlobalExceptionFilter));
}
public void OnException(ExceptionContext context)
{
if (!context.ExceptionHandled)//如果例外沒有處理
{
var result = new ApiResult
{
Code = 500,
IsSuccess = false,
Message = "服務器發生未處理的例外"
};
if (hostEnvironment.IsDevelopment())
{
result.Message += "," + context.Exception.Message;
result.Data = https://www.cnblogs.com/Start201505/p/context.Exception.StackTrace;
}
logger.Error(result);
context.Result = new JsonResult(result);
context.ExceptionHandled = true;//例外已處理
}
}
}
然后在Service中添加全域例外過濾器
builder.Services.AddControllers(option =>
{
option.Filters.Add<GlobalExceptionFilter>();
}
);
添加控制器方法完成測驗
[HttpGet("exception")]
public ApiResult ExceptionAction()
{
throw new NotImplementedException();
}
8.如何使用redis做快取
使用 StackExchange.Redis 作為快取組件(其他組件類似的使用方式),nuget 安裝 StackExchange.Redis.Extensions.Core
首先,先建立一個類 RedisClient ,用于管理redis的連接和操作,再建立一個 RedisClientFactory 類,用于創建 redis的連接;
public class RedisClient{...}
public class RedisClientFactory{...}
appsettings.json 中添加redis的配置
"RedisConfig": {
"Redis_Default": {
"Connection": "127.0.0.1:6379",
"InstanceName": "Redis1:"
},
"Redis_6": {
"Connection": "127.0.0.1:6379",
"DefaultDatabase": 6,
"InstanceName": "Redis2:"
}
}
service中添加 redis客戶端的參考
//添加redis的使用
builder.Services.AddSingleton<RedisClient>(_=> RedisClientFactory.GetInstance(builder.Configuration));
一頓操作后,就可以在你想要使用redis的地方參考了
RedisClient redisClient
...
this.redisDb = redisClient.GetDatabase("Redis_Default");
redisDb.StringSet("clientId", "clientId", TimeSpan.FromSeconds(10));
要使用redis做分布式快取,先參考 Microsoft.Extensions.Caching.StackExchangeRedis
//將Redis分布式快取服務添加到服務中
builder.Services.AddStackExchangeRedisCache(options =>
{
//用于連接Redis的配置 Configuration.GetConnectionString("RedisConnectionString")讀取配置資訊的串
options.Configuration = "Redis_6";// Configuration.GetConnectionString("RedisConnectionString");
//Redis實體名RedisDistributedCache
options.InstanceName = "RedisDistributedCache";
});
參考自 "分布式 Redis 快取"
9. 如何添加使用定時任務組件
此處使用 Hangfire 定時任務組件,輕便,可持久化,還有面板,
參考 Hangfire 后,即可新增定時任務,
//啟用Hangfire服務.
builder.Services.AddHangfire(x => x.UseStorage(new MemoryStorage()));
builder.Services.AddHangfireServer();
...
//啟用Hangfire面板
app.UseHangfireDashboard();
//開啟一個定時任務
RecurringJob.AddOrUpdate("test",() => Console.WriteLine("Recurring!"), Cron.Minutely());
訪問 https://localhost:7219/hangfire 即可看到任務面板
10. 如何使用業務鎖鎖住下單或者支付操作
首先,做這個事需要能先構建出一個鎖出來,這個鎖有個鎖的標識key,可以根據這個key判定key對應的鎖是否存在,
這樣的話,在某個用戶支付或者下單減庫存啥的時候,就可以按照這個key先上鎖,后面有用戶走其他渠道進行同樣的操作的時候,就可以根據是否上鎖了,來判斷操作能否繼續,
比如一個支付訂單的業務,可以在手機上操作,也可以在電腦上操作,這個時候就可以給支付介面上鎖,只要一個支付程序存在著,并且沒有超時,那就不能在其他渠道進行操作,
我們上面已經使用了redis,下面就用redis構建個鎖來模擬這個操作,具體看代碼:
/// <summary>
/// 測驗業務鎖
/// </summary>
/// <returns></returns>
[HttpGet("lockhandle")]
public async Task<ApiResult> LockHandle(int userId)
{
var key = "user";
var token = $"ID:{userId}";
try
{
if (redisDb.LockTake(key, token, TimeSpan.FromSeconds(50)))
{
await Task.Delay(30 * 1000);
return await Task.FromResult(ApiResult.Success($"ID:{userId} 獲取到鎖了,操作正常,connectId:{Request.HttpContext.Connection.Id}"));
}
else
{
return await Task.FromResult(ApiResult.Fail($"有正在操作的鎖,connectId:{Request.HttpContext.Connection.Id}"));
}
}
catch (Exception)
{
throw;
}
finally
{
redisDb.LockRelease(key, token);
}
}
11. 如何配置跨域
此處主要記錄全域跨域,不包括指定api跨域,先增加一個配置 "Cors": "http:127.0.0.1:5001",配置可以跨域的url,也可以使用默認跨域配置,
host配置以下服務,按需使用:
builder.Services.AddCors(delegate (CorsOptions options)
{
options.AddPolicy("CorsPolicy", delegate (CorsPolicyBuilder corsBuilder)
{
//指定url跨域
corsBuilder.WithOrigins(builder.Configuration.GetValue<string>("Cors").Split(','));
//默認跨域
corsBuilder.SetIsOriginAllowed((string _) => true).AllowAnyMethod().AllowAnyHeader()
.AllowCredentials();
});
});
12. 如何使用NewtonsoftJson
.NET6 默認的系列化庫是內置的 System.Text.Json,使用中如果有諸多不熟悉的地方,那肯定是想換回 NewtonsoftJson,需要nuget 參考 Microsoft.AspNetCore.Mvc.NewtonsoftJson 來配置使用,
常用配置包括日期格式、大小寫規則、回圈參考配置,,,等,下面是一個配置
builder.Services.AddControllers(option =>
{
option.Filters.Add<GlobalExceptionFilter>();
}
).AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); //序列化時key為駝峰樣式
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;//忽略回圈參考
});
13. 如何使用SignalR
首先添加一個 ChatHub 作為 互動中心處理器
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
在主機中使用服務
builder.Services.AddSignalR();
...
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chatHub");
});
14. 如何使用Dapper
Dapper是大家常用的一個資料庫連接擴展組件,下面介紹下,如何使用常規擴展,來在.net Core中使用Dapper,
首先,建立一個DbComponent ,來獲取由 .netCore 提供的 Configuration 組態檔,并用 DbProviderFactories 工廠,創建資料庫連接,此類只管創建連接,又其他使用類進行銷毀,
/// <summary>
/// 創建連接處理
/// </summary>
public class DbComponent
{
/// 資料庫連接配置
private static ConnectionStringSettings connectionSetting;
public static void InitDapper(ConnectionStringSettings connectionStringSettings)
{
connectionSetting = connectionStringSettings;
}
//通過工廠模式創建Connection連接 此連接已打開
public static IDbConnection GetConnection()
{
get {
var cnnection = DbProviderFactories.GetFactory(connectionSetting.ProviderName).CreateConnection();
if (cnnection == null)
throw new Exception("資料庫鏈接獲取失敗!");
cnnection.ConnectionString = connectionSetting.ConnectionString;
cnnection.Open();
return cnnection;
}
}
}
使用前,需要在program中初始化一下組件
/// <summary>
/// 初始化Dapper組件
/// </summary>
DbProviderFactories.RegisterFactory("Microsoft.Data.Sqlite", Microsoft.Data.Sqlite.SqliteFactory.Instance);
DbComponent.InitDapper(new System.Configuration.ConnectionStringSettings
{
ConnectionString = builder.Configuration.GetConnectionString("Default"),
ProviderName = "Microsoft.Data.Sqlite"
});
程式啟動后,就可以在需要的地方使用
public class UserIdentyService
{
public ApiResult DapperList()
{
using (var connect = DbComponent.Connection)
{
var users= connect.Query<User>("SELECT * FROM Users").ToList();
return ApiResult.Success(users);
}
}
}
15. 如何添加自定義組態檔
有時候我們不想把配置全部放在 appsettings.json ,我們想自己建立一個檔案夾來存盤其他組態檔,比如config/...json之類的,咋整呢,
我們新建個檔案夾 config,下面建立一個組態檔app.json,里面存幾個配置以便驗證,
使用前添加如下代碼即可
builder.Configuration.AddJsonFile("config/app.json");
Console.WriteLine(builder.Configuration.GetValue<string>("weixin"));
16. 如何簡單上傳檔案
上傳檔案是每個api框架都會實作的功能,我們先實作一個簡單的檔案上傳,
首先做個組態檔,存盤上傳的檔案存盤位置、大小及格式限制等的配置
public class UploadConfig
{
/// <summary>
/// 最大值
/// </summary>
public int MaxSize { get; set; } = 1024 * 1024 * 1024;
/// <summary>
/// 存盤路徑
/// </summary>
public string UploadDir { get; set; } = @"D://Upload";
/// <summary>
/// 站點名稱
/// </summary>
public string WebSite { get; set; }
}
添加測驗action,完成檔案上傳,并回傳檔案訪問路徑
/// <summary>
/// 上傳檔案測驗
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
[HttpPost("upload")]
public async Task<ApiResult> Upload([FromForm(Name ="file")] List<IFormFile> files)
{
var config = configuration.GetSection("UploadConfig").Get<UploadConfig>();
if (files.Count == 0)
{
return ApiResult.Fail("沒有需要上傳的檔案");
}
var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.UploadDir);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
//驗證大小或者格式之類
foreach (var file in files)
{
var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName;
var fileSize = file.Length;
if (fileSize > config.MaxSize)
{
return ApiResult.Fail($"{fileName}檔案過大");
}
}
//存盤檔案
var result = new List<string>();
foreach (var file in files)
{
var fileName = file.FileName;
using (var stream = System.IO.File.Create(Path.Combine(dir, fileName)))
{
await file.CopyToAsync(stream);
}
result.Add(string.Join('/',config.WebSite,"upload/view" fileName));
}
return ApiResult.Success(result);
}
上述檔案訪問路徑需要配置靜態目錄來進行訪問
//啟動www靜態目錄
app.UseStaticFiles();
//啟動上傳檔案目錄
app.UseStaticFiles(new StaticFileOptions {
FileProvider = new PhysicalFileProvider(builder.Configuration.GetValue<string>("UploadConfig:UploadDir")),
RequestPath = "/upload/view"
});
至此,檔案上傳及訪問已添加完成
在時間軸上留下點什么,作為個程式員,就在cnblog上吧,我不是技術大牛,也不是IT狂熱者,說不上是我選了它還是它選了我,結果是現在我是一名程式員,我對它很感興趣,不為以后做業務大佬、行業頂尖,只想在自己能力范圍內,把事情做到最好,在博客園記錄下自己的歷程吧,作業,學習,感情,生活,轉載請註明出處,本文鏈接:https://www.uj5u.com/net/396011.html
標籤:.NET Core
