錄導航:
文章正文:
回到頂部
本章主要通過一個完整的示例講解ASP.NET Core MVC+EF Core對MySQL數據庫進行簡單的CRUD操作,希望能夠為剛入門.NET Core的小伙伴們提供一個完整的參考實例。關于ASP.NET Core MVC+EF操作MsSQL Server詳情請參考官方文檔(https://docs.microsoft.com/zh-cn/aspnet/core/data/ef-mvc/?view=aspnetcore-3.1)。
回到頂部
回到頂部
https://github.com/YSGStudyHards/ASP.NET-Core-MVC-Layui-EF-Core-CRUD_Sample
回到頂部
注意,本章節主要以APS.NET Core 3.1版本作為博客的樣式實例!
回到頂部
若要在項目中使用EF Core操作MySQL數據庫,需要安裝相應的數據庫驅動包。 本章教程主要使用 MySQL數據庫,所以我們需要安裝相關驅動包MySql.Data.EntityFrameworkCore。
回到頂部
Install-Package MySql.Data.EntityFrameworkCore -Version 8.0.20
搜索:MySql.Data.EntityFrameworkCore 點擊安裝。
回到頂部
注意該篇博客使用的是手動模型優先的方式進行數據庫表字段與模型屬性映射,當然如果大家覺得這樣子比較麻煩的話可以真正意義上的模型優先,直接創建模型在program.cs中配置創建對應模型的數據庫邏輯代碼即可無需手動創建數據庫,可參考官網文檔教程(https://docs.microsoft.com/zh-cn/aspnet/core/data/ef-rp/intro?view=aspnetcore-3.1&tabs=visual-studio#create-the-database)。
注意:屬性大小寫和數據庫中的表字段保持一致,Id 屬性成為此類對應的數據庫表的主鍵列。 默認情況下,EF Core 將名為 Id 或 xxxID 的屬性視為主鍵。 有關詳細信息,請參閱 F Core - 密鑰。
/// <summary>
/// 學生信息模型
/// </summary>
public class UserInfo
{
/// <summary>
/// 學生編號
/// </summary>
[Description("學生編號")]
public int? Id { get; set; }
/// <summary>
/// 學生姓名
/// </summary>
[Description("學生姓名")]
public string UserName { get; set; }
/// <summary>
/// 學生性別
/// </summary>
[Description("學生性別")]
public string Sex { get; set; }
/// <summary>
/// 學生聯系電話
/// </summary>
[Description("學生聯系電話")]
public string Phone { get; set; }
/// <summary>
/// 學生描述
/// </summary>
[Description("學生描述")]
public string Description { get; set; }
/// <summary>
/// 學生愛好
/// </summary>
[Description("學生愛好")]
public string Hobby { get; set; }
}
回到頂部
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MySqlConnection":"Data Source=127.0.0.1;User ID=root;Password=root;DataBase=SchoolUserInfo_db"
}
}
回到頂部
數據庫上下文類是為給定數據模型協調 EF Core 功能的主類。 上下文派生自 Microsoft.EntityFrameworkCore.DbContext。 上下文指定數據模型中包含哪些實體。 在此項目中將數據庫上下文類命名為 SchoolUserInfoContext。
using Microsoft.EntityFrameworkCore;
using Model;
namespace Dal
{
public class SchoolUserInfoContext : DbContext
{
public SchoolUserInfoContext(DbContextOptions<SchoolUserInfoContext> options)
: base(options)
{
}
/// <summary>
/// DbSet實體集屬性對應數據庫中的表(注意實體集名必須與表明一致)
/// </summary>
public DbSet<UserInfo> UserInfos { get; set; }
/// <summary>
/// TODO:當數據庫創建完成后, EF 創建一系列數據表,表名默認和 DbSet 屬性名相同。 集合屬性的名稱一般使用復數形式,但不同的開發人員的命名習慣可能不一樣,
/// 開發人員根據自己的情況確定是否使用復數形式。 在定義 DbSet 屬性的代碼之后,添加下面代碼,對DbContext指定單數的表名來覆蓋默認的表名。
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserInfo>().ToTable("UserInfo");
}
}
}
回到頂部
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//注入EF Core數據庫上下文服務
services.AddDbContext<SchoolUserInfoContext>(options=>
options.UseMySQL(Configuration.GetConnectionString("MySqlConnection")));
services.AddControllersWithViews();
}
回到頂部
前往官網下載Layui相關樣式和js包,下載地址:https://www.layui.com/
Layui彈出層插件layer.js(有很多地方需要用到彈窗),下載地址:https://layer.layui.com/
回到頂部
注意在這里主要展示的EF Core與數據庫操作的部分代碼,詳細代碼可下載實例源碼查看。
/// <summary>
/// 學生信息添加
/// </summary>
/// <param name="addUserInfo"></param>
/// <returns></returns>
public async Task<bool> Create(AddUserInfoViewModel addUserInfo)
{
try
{
var userInfo=new UserInfo()
{
UserName=addUserInfo.UserName,
Sex=addUserInfo.Sex,
Hobby=addUserInfo.Hobby,
Phone=addUserInfo.Phone,
Description=addUserInfo.Description
};
_shoSchoolUserInfoContext.UserInfos.Add(userInfo);
await _shoSchoolUserInfoContext.SaveChangesAsync();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 獲取用戶信息
/// </summary>
/// <param name="page">當前頁碼</param>
/// <param name="limit">顯示條數</param>
/// <param name="userName">用戶姓名</param>
/// <returns></returns>
public async Task<PageSearchModel> GetPageListData(int page=1, int limit=15, string userName="")
{
try
{
List<UserInfo> listData;
var totalCount=0;
if (!string.IsNullOrWhiteSpace(userName))
{
listData=await _shoSchoolUserInfoContext.UserInfos.Where(x=> x.UserName.Contains(userName)).OrderByDescending(x=> x.Id).Skip((page - 1) * limit).Take(limit).ToListAsync();
totalCount=_shoSchoolUserInfoContext.UserInfos
.Count(x=> x.UserName.Contains(userName));
}
else
{
listData=await _shoSchoolUserInfoContext.UserInfos.OrderByDescending(x=> x.Id).Skip((page - 1) * limit).Take(limit).ToListAsync();
totalCount=_shoSchoolUserInfoContext.UserInfos.Count();
}
return new PageSearchModel()
{
ResultMsg="success",
Code=200,
TotalCount=totalCount,
DataList=listData
};
}
catch (Exception e)
{
return new PageSearchModel() { Code=400, ResultMsg=e.Message };
}
}
/// <summary>
/// 學生信息修改
/// </summary>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task<bool> Update(UserInfo userInfo)
{
try
{
_shoSchoolUserInfoContext.UserInfos.Update(userInfo);
await _shoSchoolUserInfoContext.SaveChangesAsync();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 學生信息刪除
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<bool> Delete(int? id)
{
try
{
var searchUserInfo=await _shoSchoolUserInfoContext.UserInfos.FindAsync(id);
if (searchUserInfo==null)
{
return false;
}
_shoSchoolUserInfoContext.UserInfos.Remove(searchUserInfo);
await _shoSchoolUserInfoContext.SaveChangesAsync();
return true;
}
catch
{
return false;
}
}
作者:追逐時光
原文:https://www.cnblogs.com/Can-daydayup/p/12593599.html
日客戶要求表內的數據依據某種分組生成HTML頁面進行展示,一般處理這種需求直接上編程工具就好了,從數據庫里讀取數據,根據規則生成字符串,最后將字符串寫出到文件。由于需求比較急,作為數據庫編程系列文章,如果能用SQL實現首選還是SQL,這樣處理既直接又快速,不過針對SQL要真的有耐心和信心寫完,調試更是崩潰。由于要寫出文件到硬盤,最后還是選擇MySQL作為數據庫工具,Navicat作為開發工具。
有兩張表計劃表、市縣表,二者依靠市縣編碼(sxbm)進行等值連接,計劃表內含有各個學校投放在各個市縣的專業代號(zydh),專業名稱(zymc)、招生備注(bz)、學制(xz)、要求的學歷(xl)、計劃數(jh)等字段組成的計劃信息,院校編碼(yxbm)為學校的兩位數編碼,院校代號(yxdh)為院校編碼(yxbm)+市縣編碼(sxbm)組成的四位數編碼,院校代號其實可以區分出學校在哪個市縣的投檔的專業計劃。要求以學校為單位創建HTML頁面,頁面首先要以市縣作為表格分割,然后根據專業代號排序。具體實現過程如下:
CREATE TABLE `zzjh2019v` ( `YXDH` varchar(9) COMMENT '學校代號', `YXMC` varchar(54) COMMENT '學校名稱', `ZYDH` varchar(2) COMMENT '專業代號', `ZYMC` varchar(28) COMMENT '專業名稱', `XZ` varchar(3) COMMENT '學制', `XL` varchar(4) COMMENT '學歷', `JH` varchar(6) COMMENT '招生計劃數', `BZ` varchar(200) COMMENT '備注', `yxbm` char(2) COMMENT '學校編碼', `sxbm` char(2) COMMENT '市縣編碼' ) ENGINE=InnoDB CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=Compact;
CREATE TABLE `sx` ( `sxbm` char(2) COMMENT '市縣編碼', `sxmc` varchar(20) COMMENT '市縣名稱' ) ENGINE=InnoDB CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=Compact;
糾結了很久這個東西怎么寫,最后采取游標、拼接字符串、字符串聚合,動態SQL,寫文件等一些列操作完成需求,創建的存儲過程如下:
CREATE DEFINER=`root`@`localhost` PROCEDURE `splitjh`() BEGIN declare done INT DEFAULT 0; declare pyxbm char(2); declare psxmc varchar(10); declare pyxmc varchar(50); declare pjhall int; declare pjhrows TEXT; declare yxjh cursor for select yxbm,yxmc,sum(jh) jhall from zzjh2019v a,sx b where a.sxbm=b.sxbm group by yxbm,yxmc order by yxbm; declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; open yxjh; fetch yxjh into pyxbm,pyxmc,pjhall; while done !=1 do select group_concat(jhrow separator '') into pjhrows from (select concat('<tr class="subtitle"><td>',yxdh,'</td><td>',yxmc,'在 <span><font color="red">',b.sxmc,'</font></span> 招生計劃如下</td><td>',sum(jh),'</td><td></td><td></td></tr>',group_concat('<tr class="jhrow"><td>',zydh,'</td><td>',zymc,'(',bz,')</td><td>',jh,'</td><td>',xz,'</td><td>',xl,'</td></tr>' order by zydh separator '')) jhrow from zzjh2019v a,sx b where yxbm=pyxbm and a.sxbm=b.sxbm group by yxdh order by yxdh,zydh) jhs; set @pfilename=concat('''d:/32/1/1/jh11',pyxbm,'.html'''); set @sql=concat('select concat(''<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><link rel="stylesheet" type="text/css" href="zsjh.css" ><title>3+2計劃</title></head><body><h3></h3><table><tr class="subtitle"><th>代號</th><th>專業及名稱備注</th><th>人數</th><th>學制</th><th>學歷</th></tr>'',''',pjhrows,''',''</body></html>'') from dual into outfile ',@pfilename); prepare execsql from @sql; execute execsql; DEALLOCATE PREPARE execsql; fetch yxjh into pyxbm,pyxmc,pjhall; end while; close yxjh; END;
首先看效果,執行過程
call splitjh();
在磁盤形成的HTML文件效果如下圖(數據有一定的敏感性,進行了遮擋處理):
文件展示頁面
生成的文件列表如下圖:
生成的文件列表
這里一共有87所學校,所以生成了87的文件,添加CSS樣式文件,讓表格呈現如前圖所示。
技術點
1)MySQL的游標,以及循環讀取游標的方法,涉及的語句如下:
declare yxjh cursor for select yxbm,yxmc,sum(jh) jhall from zzjh2019v a,sx b where a.sxbm=b.sxbm group by yxbm,yxmc order by yxbm;#游標定義 declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;#游標循環條件,注意此句一定要定義在游標之后,才起作用 open yxjh;#打開游標 fetch yxjh into pyxbm,pyxmc,pjhall;#將游標行內容賦值給變量。
2)執行動態SQL,由于MySQL into outfile 后接的文件名不能為變量,所以必須使用動態SQL的方法,涉及的語句如下:
prepare execsql from @sql;#從一個變量準備一個動態sql,注意execsql不用提前定義 execute execsql;#執行準備好的語句 DEALLOCATE PREPARE execsql;#銷毀語句
綜上就是使用MySQL數據庫,并借用MySQL寫文件的方式將數據從數據庫內按照需求導出文件,為何不用navicat導出呢?因為無法達到要求,又是聚合、又是格式,所以只能自己編寫過程通過SQL語句拼接字符串的方式來實現。沒有太多的技術難度,主要是想法和調試難度。后續在此基礎上又開發了以市縣為單位創建HTML文件,各招生學校作為分割的過程。本案例是實際需求催生出來的做法,在遇到這樣的需求前你是先想到SQL還是先想到開發工具呢?從實際效果看使用SQL這種方式更加靈活。這樣的SQL實現的字符串拼接是不是有點極限呢?
言
嘮嗑一下。都在說去O或者開源,但是對于數據庫選型來說,很多人卻存在著誤區。例如,去O,狹義上講,是去Oracle數據庫。但是從廣義上來說,是去Oracle公司產品或者具有漂亮國壟斷地位和需要商業授權的數據庫產品。
去O,目前國內有一個現象,就是很多公司或個人聽到去O,第一反應是改用Mysql,實際上Mysql也是Oracle公司的。而且Mysql雖然是開源的,但是需要遵循GPL開源協議,這個協議里面(大概意思)含有這么兩點就可以窺見一斑:
1、如果用Mysql源碼進行二次修改,修改后的產品也必須開源,例如目前國產分布式數據庫TiDB就遵循該協議進行開源;
2、如果要對Mysql二次封裝或者修改后進行實現商業版本,就必須取得甲骨文公司授權。以上這兩條,就足以讓Mysql這款開源數據庫并不具備“開源優勢”,將來該被制裁還是會被制裁。
目前去O,還有一款備選開源數據庫是PostgreSQL,它是基于BSD開源協議的,該開源協議是四大開源協議里面最“開放”和自由的,不會受到商業版權化影響,并且組織或個人也可以通過它的源碼進行二次封裝或者進行發行商業版,例如華為的OpenGuass是基于該開源版本進行二次開發的,并且基于PostgreSQL或者基于OpenGuass進行二次封裝成商業版本的數據庫(國產、非國產等)也比比皆是。
以上只是吐個槽,本篇文章主要是想通過.NET6+EF CORE + 三大數據庫,進行一個在同等環境下的簡單的讀寫性能測試。
【備注】由于各種原因,接下來的測試結果可能會不準確,以下僅供學習或參考使用。
數據庫運行環境:Cent OS 7.5
PostgreSQL版本:14
MySQL數據庫版本:8.0
Oracle數據庫:12C 64位
客戶端環境:WIN 10 專業版
運行時環境:.NET 6
ORM:EF CORE
開發語言:C#
CentOS環境安裝PostgreSQL
遠程服務器上已有授權的Oracle環境和Mysql環境,所以具體安裝細節不再進行描述,如果感興趣的小伙伴也可以自行百度一下Oracle和Mysql的安裝教程,應該非常多。由于服務器上暫時還沒有PostgreSQL環境,我暫且也把安裝PostgreSQL的安裝步驟也順手記錄下。
PostgreSQL安裝:
下載地址:
https://www.postgresql.org/download/linux/redhat/
選擇版本以后,會有對應提示的安裝方式命令,就不發出來了,可自行參考。
以下是安裝以后的一些配置。
安裝完畢,并且啟動pgsql服務以后,此處我先創建一個測試用的數據庫:testdb
使用命令:su - postgres 可以進行默認的登錄,默認無密碼。
登陸以后使用命令:psql 可以進入到可執行SQL的命令的頁面,以postgres=# 開頭。其他命令和有關創建用戶的SQL語句如圖所示。
修改配置文件: /var/lib/pgsql/14/data/postgresql.conf
將注釋的listen_addresses打開,設置值為 ‘*’
路徑上的14代表版本,如果是13版本就是13,以此類推,下同。
修改/var/lib/pgsql/14/data/pg_hba.conf配置文件,對IPV4訪問新增一行配置如下:
然后要重啟pgsql服務,以用于生效。
由于pgsql默認的端口是5432,為了可以跨遠程訪問,此處把遠程服務器上的端口開放出來。命令:firewall-cmd --zone=public --add-port=5432/tcp --permanent
然后重載防火墻,命令:firewall-cmd --reload
測試數據庫有關表結構。以下表均沒有設置索引,僅單表測試,結果僅供參考。
Mysql表結構:
PostgreSQL表結構:
Oracle表結構:
.NET 6開發測試代碼
先創建一個minimal api項目,以及一個服務類庫項目。類庫引用需要操作Oracle數據庫、MySQL數據庫以及Postgresql數據庫有關的組件。
對服務類設置為啟動項,然后新增三個文件夾(MyModel,OraModel和PgModel),用于分別存放三個數據庫的實體類。然后在程序包管理控制臺上,通過命令:
Scaffold-DbContext “mysql連接字符串" Pomelo.EntityFrameworkCore.MySql -OutputDir MyModel -Force
自動生成指定的mysql數據庫實體類。其中,MyModel是需要生成的目標目錄文件夾。
通過命令:
Scaffold-DbContext "Oracle連接字符串" Oracle.EntityFrameworkCore -OutputDir OraModel -Force
自動生成Oracle數據庫實體類。
通過命令:
Scaffold-DbContext "pgsql連接字符串" Npgsql.EntityFrameworkCore.PostgreSQL -OutputDir PgModel -Force
自動生成PostgreSQL數據庫實體類。
新建一個測試服務類DatabaseTestService,提供簡單插入和更新功能:
在minimai api項目里,新增兩個簡單的測試API用于測試。為了簡單,就直接實例化一下進行訪問,然后返回執行結果。
以上方法可能執行適合會導致耗時而失敗,為了直觀一點,改成控制臺里面輸出。
實現里面也做點調整。
測試插入和更新
運行程序以后,對三個數據庫分別插入數據并計時。
先看Oracle物理表情況。
插入總共數據條數:
部分數據結果集:
然后是mysql物理表數據。
插入數據總數:
部分數據結果集:
最后是PostgreSQL。插入總條數:
部分數據結果集:
以下是通過EF CORE進行插入的結果:
接下來進行一輪更新操作,為了防止數據量太大,所以只進行批量更新10000條數據。結果如下:
看下數據更新結果是不是正常。
Oracle數據:
MySQL數據:
PGSQL數據:
數據庫數據清空,屏蔽掉C#代碼一些實體賦值時間,重新執行兩次僅統計批量插入數據庫部分的執行的時間進行重新測試,僅測試批量插入耗時結果。
第一回測試結果:
接下來不刪除數據,重新執行一輪。
Oracle估計哪兒有問題,數據讓人很尷尬啊。接下來只比較MySQL和PgSQL
來一波批量插入:
再來一波三次的批量更新:
有關代碼(最后測試使用):
public class DatabaseTestService
{
public String TestInsert()
{
StringBuilder sb=new StringBuilder();
Console.WriteLine("*************************開始插入測試************************");
for(int i=1; i < 5; i++)
{
// Console.WriteLine(TestOracleInsert(i));
Console.WriteLine(TestMysqlInsert(i));
Console.WriteLine(TestPostgreSQLInsert(i));
}
return sb.ToString();
}
public String TestUpdate()
{
StringBuilder sb=new StringBuilder();
Console.WriteLine("*************************開始更新測試************************");
// Console.WriteLine(TestOracleUpdate());
for (int i=0;i<3;i++) {
Console.WriteLine(TestMysqlUpdate(i));
Console.WriteLine(TestPostgreSQLUpdate(i));
}
return sb.ToString();
}
private String TestOracleInsert(int loop)
{
StringBuilder sb=new();
Stopwatch stopwatch=new();
List<OraModel.TestTable> tables=new();
for (int i=1; i <=50000; i++)
{
OraModel.TestTable table=new();
table.Id=Guid.NewGuid().ToString("N");
table.Message=$"第{loop}輪測試數據{i}";
table.CurrentTime=DateTime.Now;
table.Code=(loop * 5000) + i;
tables.Add(table);
}
using (var context=new OraModel.ModelContext())
{
try {
stopwatch.Start();
context.Database.BeginTransaction();
context.TestTables.AddRange(tables);
context.SaveChanges();
context.Database.CommitTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪插入50000條到【Oracle】數據庫【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
catch(Exception ex)
{
context.Database.RollbackTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪插入50000條到【Oracle】數據庫【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
finally
{
}
}
return sb.ToString();
}
private String TestMysqlInsert(int loop)
{
StringBuilder sb=new();
Stopwatch stopwatch=new();
List<MyModel.TestTable> tables=new();
for (int i=1; i <=100000; i++)
{
MyModel.TestTable table=new();
table.Id=Guid.NewGuid().ToString("N");
table.Message=$"第{loop}輪測試數據{i}";
table.CurrentTime=DateTime.Now;
table.Code=i;
tables.Add(table);
}
using (var context=new MyModel.testdbContext())
{
try
{
stopwatch.Start();
context.Database.BeginTransaction();
context.TestTables.AddRange(tables);
context.SaveChanges();
context.Database.CommitTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪插入100000條到【MySQL】數據庫【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
catch (Exception ex)
{
context.Database.RollbackTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪插入100000條到【MySQL】數據庫【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
finally
{
}
}
return sb.ToString();
}
private String TestPostgreSQLInsert(int loop)
{
StringBuilder sb=new();
Stopwatch stopwatch=new();
List<PgModel.TestTable> tables=new();
for (int i=1; i <=100000; i++)
{
PgModel.TestTable table=new();
table.Id=Guid.NewGuid().ToString("N");
table.Message=$"第{loop}輪測試數據{i}";
table.CurrentTime=DateTime.Now;
table.Code=i;
tables.Add(table);
}
using (var context=new PgModel.testdbContext())
{
try
{
stopwatch.Start();
context.Database.BeginTransaction();
context.TestTables.AddRange(tables);
context.SaveChanges();
context.Database.CommitTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪插入100000條到【PostgreSQL】數據庫【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
catch (Exception ex)
{
context.Database.RollbackTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪插入100000條到【PostgreSQL】數據庫【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
finally
{
}
}
return sb.ToString();
}
private String TestOracleUpdate()
{
StringBuilder sb=new();
Stopwatch stopwatch=new();
using (var context=new OraModel.ModelContext())
{
var datas=context.TestTables.OrderBy(x=>x.Code).Take(10000);
context.Database.BeginTransaction();
foreach (var value in datas)
{
value.Message=$"數據變更,code={value.Code}";
}
try
{
stopwatch.Start();
context.TestTables.UpdateRange(datas);
context.SaveChanges();
context.Database.CommitTransaction();
stopwatch.Stop();
sb.Append($"批量更新【Oracle】數據庫10000條【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
catch (Exception ex)
{
context.Database.RollbackTransaction();
stopwatch.Stop();
sb.Append($"批量更新【Oracle】數據庫10000條【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
finally
{
}
}
return sb.ToString();
}
private String TestMysqlUpdate(int loop)
{
StringBuilder sb=new();
Stopwatch stopwatch=new();
using (var context=new MyModel.testdbContext())
{
var datas=context.TestTables.OrderBy(x=> x.Code).Skip(loop*50000).Take(50000);
context.Database.BeginTransaction();
foreach (var value in datas)
{
value.Message=$"數據變更,code={value.Code}";
}
try
{
stopwatch.Start();
context.TestTables.UpdateRange(datas);
context.SaveChanges();
context.Database.CommitTransaction();
stopwatch.Stop();
sb.Append($"批量更新【MySQL】數據庫50000條【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
catch (Exception ex)
{
context.Database.RollbackTransaction();
stopwatch.Stop();
sb.Append($"批量更新【MySQL】數據庫50000條【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
finally
{
}
}
return sb.ToString();
}
private String TestPostgreSQLUpdate(int loop)
{
StringBuilder sb=new();
Stopwatch stopwatch=new();
using (var context=new PgModel.testdbContext())
{
var datas=context.TestTables.OrderBy(x=> x.Code).Skip(loop * 50000).Take(50000);
context.Database.BeginTransaction();
foreach (var value in datas)
{
value.Message=$"數據變更,code={value.Code}";
}
try
{
stopwatch.Start();
context.TestTables.UpdateRange(datas);
context.SaveChanges();
context.Database.CommitTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪 批量更新【PostgreSQL】數據庫50000條【成功】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
catch (Exception ex)
{
context.Database.RollbackTransaction();
stopwatch.Stop();
sb.Append($"第{loop}輪 批量更新【PostgreSQL】數據庫50000條【失敗】:耗時{stopwatch.ElapsedMilliseconds} ms...");
}
finally
{
}
}
return sb.ToString();
}
}
以上測試至此就結束了。結論可能有點尷尬,也許跟環境配置有關,也可能跟ef core操作數據庫的支持與實現有關。并且當前僅在單表環境下測試,并沒有通過多表測試、存過測試、壓力測試等,結果僅供娛樂和參考。同時歡迎各位大佬們提供更多測試內容,也歡迎各位大佬轉發或評論或點贊等一鍵三連。
本文原鏈接:https://www.cnblogs.com/weskynet/p/16097151.html
*請認真填寫需求信息,我們會在24小時內與您取得聯系。