mssql分頁代碼(sqlserver分頁查詢)
Gradual evolution 項目說明
實現(xiàn)目標:使用 FreeSql 無縫接替 EF Core ,并實現(xiàn)數(shù)據(jù)表的 CRUD 操作;
實現(xiàn)目標:使用 FreeSql 無縫接替 EF Core ,并實現(xiàn)數(shù)據(jù)表的 CRUD 操作;
接下來我們先回顧下 EF Core 中如何實現(xiàn)數(shù)據(jù)表的 CRUD 操作,在操作之前我們先把數(shù)據(jù)庫和相關表結構準備好。
DB 數(shù)據(jù)表結構
數(shù)據(jù)庫實例名稱: Test
數(shù)據(jù)表結構: User
數(shù)據(jù)庫實例名稱: Test
數(shù)據(jù)表結構: User
此處為了方便演示,創(chuàng)建一個簡單的 User 表,數(shù)據(jù)結構如下:
字段
說明
Id
主鍵,用戶ID
Name
用戶姓名
DB 數(shù)據(jù)表創(chuàng)建
創(chuàng)建數(shù)據(jù)庫實例 Test 和 User 表,執(zhí)行如下 sql 腳本:
USEmaster;
GO
-- 創(chuàng)建 Test
展開全文
CREATEDATABASETest
ON
( NAME= Test_dat,
FILENAME = 'D:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\testdat.mdf',
SIZE= 10,
MAXSIZE= 50,
FILEGROWTH = 5)
LOGON
( NAME= Test_log,
FILENAME = 'D:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\testlog.ldf',
SIZE= 5MB,
MAXSIZE= 25MB,
FILEGROWTH = 5MB );
GO
CREATETABLETest.dbo.[ User] (
Idvarchar( 36) NOTNULLprimary key,
Namevarchar( 20) NOTNULL
);
EXEC Test.sys.sp_addextendedproperty 'MS_Deion', N'用戶信息', 'schema', N'dbo', 'table', N'User';
GO
執(zhí)行上面 sql 腳本創(chuàng)建數(shù)據(jù)庫失敗時,可以先執(zhí)行如下 sql 腳本,然后在繼續(xù)執(zhí)行上面步驟。
-- 關閉數(shù)據(jù)庫連接并刪除數(shù)據(jù)庫
ALTERDATABASETestSETSINGLE_USER WITHROLLBACKIMMEDIATE;
DROPDATABASETest;
除了上面常規(guī)的 mssql 配置,開發(fā)環(huán)境為了方便快捷,還可以使用 Docker 運行 mssql 鏡像( mcr.microsoft.com/mssql/server ),此處我是配置的 Docker 環(huán)境(這里不做詳細介紹,感興趣的小伙伴自行查看資料):
docker-mssql-2017
到這里我們就把基本的開發(fā)環(huán)境準備好了,接下來就是新建項目相關環(huán)節(jié)的操作。
數(shù)據(jù)表 User 實體模型創(chuàng)建
依據(jù)上面的 User 表結構,在(新建)項目 Jeff.Mes.EntityFrameworkCore 中添加 C# 模型類:
usingSystem.ComponentModel.DataAnnotations.Schema;
namespaceJeff.Mes.EntityFrameworkCore;
///summary
///用戶信息表
////summary
[ Table( "User") ]
publicclassUser
{
///summary
///主鍵,用戶ID
////summary
publicstringId { get; set; }
///summary
///用戶姓名
////summary
publicstringName { get; set; }
}
使用 EF Core 實現(xiàn) User 表新增用戶信息
上面我們準備好 Test 數(shù)據(jù)庫、User 表和 C# 實體模型結構 后,接下來準備編寫 EF Core 相應的操作代碼。
添加 EF Core 相關的 nuget 包
說明:此處環(huán)境使用的 SqlServer 數(shù)據(jù)庫,其他類型的數(shù)據(jù)庫需添加相應的 nuget 包。
說明:此處環(huán)境使用的 SqlServer 數(shù)據(jù)庫,其他類型的數(shù)據(jù)庫需添加相應的 nuget 包。
接著我們繼續(xù)在上面新建的項目【 Jeff.Mes.EntityFrameworkCore 】中改造,添加 nuget 包:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.SqlServer
efcore.sqlserver 編寫 EF Core 操作 User 表的 CRUD 代碼
項目【 Jeff.Mes.EntityFrameworkCore 】中添加 FreeSql 的 Nuget 包:
FreeSql.Provider.SqlServer
FreeSql.Provider.SqlServer
FreeSql.Provider.SqlServer
在項目【 Jeff.Mes.EntityFrameworkCore 】中新建 TestContext 類,繼承 DbContext ,實現(xiàn)如下:
usingMicrosoft.EntityFrameworkCore;
usingSystem.ComponentModel.DataAnnotations.Schema;
namespaceJeff.Mes.EntityFrameworkCore;
///summary
///Test 數(shù)據(jù)庫上下文對象
////summary
publicclassTestContext: DbContext
{
publicTestContext( ) { }
///summary
///用戶信息表
////summary
publicvirtualDbSetUser User { get; set; }
protectedoverridevoidOnConfiguring( DbContextOptionsBuilder optionsBuilder)
{
if(!optionsBuilder.IsConfigured)
{
// db 連接字符串,其中符號 “***” 代表數(shù)據(jù)庫訪問密碼
stringdbConnString = "Data Source=.;Initial Catalog=Test;Persist Security Info=True;User ID=sa;Password=***";
optionsBuilder.UseSqlServer(dbConnString);
}
}
///summary
///【EF Core 模式】添加用戶測試
////summary
///returns/returns
publicasyncTask int AddUserAsync( )
{
using( vardbContext = newTestContext)
{
varguid = Guid.NewGuid.ToString;
varuser = newUser
{
Id = guid,
Name = $"efcore- {guid.Substring( 0, 5)} "
};
dbContext.Add(user);
returnawaitdbContext.SaveChangesAsync;
}
}
// 注意對比下面的,【FreeSql 模式】添加用戶測試
}
上面操作 User 表的 CRUD 代碼,為了簡化此處只寫 AddUserAsync 添加操作,其他代碼就不在詳細介紹。
FreeSql 使用 DbContext 接替 EF Core
在 Entity Framework(簡稱 EF) 中創(chuàng)建模型后,應用程序所交互的主要類是 System.Data.Entity.DbContext (通常稱為 上下文類 )。默認情況下,上下文管理與數(shù)據(jù)庫的連接。
單例對象構造器 SingletonConstructor
單例對象構造器 SingletonConstructor 代碼如下:
namespaceJeff.Mes.Common;
///summary
///單例對象構造器
////summary
///typeparam name="T"/typeparam
publicclassSingletonConstructor T whereT: class, new
{
privatestaticT? _Instance;
privatereadonlystaticobject_lockObj = new;
///summary
///獲取單例對象的實例
////summary
///returns/returns
publicstaticT GetInstance( )
{
if(_Instance != null) return_Instance;
lock(_lockObj)
{
if(_Instance == null)
{
varitem = System.Activator.CreateInstanceT;
System.Threading.Interlocked.Exchange( ref_Instance, item);
}
}
return_Instance;
}
}
使用 SingletonConstructor 構建 IFreeSql
新建 FreeSqlHelper.cs 文件,使 FreeSqlHelper 類繼承自 SingletonConstructor 單例構造器,代碼示例如下:
usingSystem.Collections.Concurrent;
usingFreeSql;
usingJeff.Mes.Common;
namespaceJeff.Mes.DbHelper;
///summary
///【Singleton 單例模式】構建 freesql 對象
////summary
publicsealedclassFreeSqlHelper: SingletonConstructor FreeSqlHelper
{
//連接字符串作為 key,存儲構建的 IFreeSql 對象的字典集合
privatereadonlystaticConcurrentDictionary string, IFreeSql _FreeDic = new;
# region構建 freesql 對象
publicIFreeSql? FreeBuilder( stringdbType, stringconnStr)
{
if( string.IsNullOrWhiteSpace(dbType) || string.IsNullOrWhiteSpace(connStr))
{
returndefault;
}
boolisOk = _FreeDic.TryGetValue(connStr, outIFreeSql? fsql);
if(isOk)
{
returnfsql;
}
DataType dataType;
stringmyDbType = dbType.Contains( '.') ? dbType.Substring(dbType.LastIndexOf( '.') + 1) : dbType;
switch(myDbType.ToLower)
{
case"mysql":
dataType = DataType.MySql;
break;
default:
dataType = DataType.SqlServer;
break;
}
returnFreeBuilder(dataType, connStr);
}
publicIFreeSql? FreeBuilder(DataType dbType, stringconnStr)
{
if( string.IsNullOrWhiteSpace(connStr))
{
returndefault;
}
/*
bool hasKey = _FreeDic.ContainsKey(connStr);
if (hasKey)
{
return _FreeDic[connStr];
}*/
boolisOk = _FreeDic.TryGetValue(connStr, outIFreeSql? fsql);
if(isOk)
{
returnfsql;
}
fsql = newFreeSqlBuilder
.UseConnectionString(dbType, connStr)
.UseAutoSyncStructure( false) //自動同步實體結構到數(shù)據(jù)庫
.Build; //請務必定義成 Singleton 單例模式
boolisAdd = _FreeDic.TryAdd(connStr, fsql);
if(isAdd)
{
returnfsql;
}
else
{
fsql.Dispose;
return_FreeDic[connStr];
}
}
public( boolisOk, IFreeSql? fsql) GetFreeSql(DataType dbType, stringconnStr)
{
boolisOk = _FreeDic.TryGetValue(connStr, outIFreeSql? fsql);
if(!isOk)
{
fsql = FreeBuilder(dbType, connStr);
isOk = fsql != null;
}
return(isOk, fsql ?? default);
}
# endregion
}
使用 FreeSqlHelper 對象構建 IFreeSql ,如下代碼:
IFreeSql fsql = FreeSqlHelper.GetInstance.FreeBuilder(dbType, connStr);
上面環(huán)節(jié)我們就準備好了 IFreeSql 對象的構建,萬事俱備,只欠東風(下面我們解析解析 DbContext 獲取有效信息);
反射解析 DatabaseFacade
在反射解析 DbContext 對象之前,我們先回顧下相關概念定義和類庫基本信息。
EF Core 中 DbContext 官方定義
Microsoft.EntityFrameworkCore.DbContext
Microsoft.EntityFrameworkCore.DbContext
上面我簡單的介紹了 DbContext 是 EF Core 的 數(shù)據(jù)庫連接對象,接下來我們看下官方定義:
命名空間: Microsoft.EntityFrameworkCore
程序集: Microsoft.EntityFrameworkCore.dll
Nuget 包: Microsoft.EntityFrameworkCore v7.0.0
命名空間: Microsoft.EntityFrameworkCore
程序集: Microsoft.EntityFrameworkCore.dll
Nuget 包: Microsoft.EntityFrameworkCore v7.0.0
DbContext 實例表示與數(shù)據(jù)庫的會話,可用于查詢和保存實體的實例。 DbContext 是工作單元和存儲庫模式的組合。
publicclassDbContext: IAsyncDisposable,
IDisposable, Microsoft. EntityFrameworkCore. Infrastructure. IInfrastructure IServiceProvider,
Microsoft. EntityFrameworkCore. Internal. IDbContextDependencies,
Microsoft. EntityFrameworkCore. Internal. IDbContextPoolable,
Microsoft. EntityFrameworkCore. Internal. IDbSetCache
關于 DbContext 更多信息,請查看 =》https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.entityframeworkcore.dbcontext?view=efcore-7.0
關于 DbContext 更多信息,請查看 =》https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.entityframeworkcore.dbcontext?view=efcore-7.0
Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade
Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade
DatabaseFacade 類定義如下:
命名空間: Microsoft.EntityFrameworkCore.Infrastructure
程序集: Microsoft.EntityFrameworkCore.dll
Nuget 包: Microsoft.EntityFrameworkCore v7.0.0
命名空間: Microsoft.EntityFrameworkCore.Infrastructure
程序集: Microsoft.EntityFrameworkCore.dll
Nuget 包: Microsoft.EntityFrameworkCore v7.0.0
提供對上下文的數(shù)據(jù)庫相關信息和操作的訪問。此類的實例通常是從 Database 中獲取的,它不是在應用程序代碼中直接構造的。
publicclassDatabaseFacade:
Microsoft. EntityFrameworkCore. Infrastructure. IInfrastructure IServiceProvider,
Microsoft. EntityFrameworkCore. Infrastructure. IResettableService,
Microsoft. EntityFrameworkCore. Storage. IDatabaseFacadeDependenciesAccessor
關于 DatabaseFacade 更多信息,請查看 =》https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.entityframeworkcore.infrastructure.databasefacade?view=efcore-7.0
關于 DatabaseFacade 更多信息,請查看 =》https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.entityframeworkcore.infrastructure.databasefacade?view=efcore-7.0
Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade
Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade
添加反射解析 DatabaseFacade 對象的代碼:
///summary
///根據(jù)對象實例和屬性名稱獲得屬性值
////summary
///typeparam name="T"/typeparam
///param name="obj"/param
///param name="property"/param
///returns/returns
publicstaticT? GetPropertyT( thisobjectobj, stringproperty)
{
varresult = default(T);
try
{
vart = obj.GetType;
varpropertyObj = t.GetProperty(property)?.GetValue(obj, null);
result = (T?)propertyObj.ChangeType( typeof(T));
returnresult;
}
catch(Exception ex)
{
throwex;
}
}
///summary
///類型轉換
////summary
///param name="value"/param
///param name="type"/param
///returns/returns
publicstaticobject? ChangeType( thisobject? value, Type type)
{
if( value== null type.IsGenericType) returnActivator.CreateInstance(type);
if( value== null) returnnull;
if(type == value.GetType) returnvalue;
if(type.IsEnum)
{
if( valueisstringvalEnum) returnEnum.Parse(type, valEnum);
elsereturnEnum.ToObject(type, value);
}
if(!type.IsInterface type.IsGenericType)
{
Type innerType = type.GetGenericArguments[ 0];
object? innerValue = ChangeType( value, innerType);
returnActivator.CreateInstance(type, newobject?[] { innerValue });
}
if( valueisstringvalGuid type == typeof(Guid)) returnnewGuid(valGuid);
if( valueisstringvalVersion type == typeof(Version)) returnnewVersion(valVersion);
if( valueisGuid type == typeof( string)) returnvalue.ToString;
if( valueisnot IConvertible) returnvalue;
if(type.IsGenericType type.GetGenericTypeDefinition.Equals( typeof(Nullable)))
{
varunderlyingType = Nullable.GetUnderlyingType(type);
type = underlyingType ?? type;
} // end if
returnConvert.ChangeType( value, type);
}
繼續(xù)在 TestContext.cs 類中添加如下代碼:
///summary
///【FreeSql 模式】添加用戶測試
////summary
///returns/returns
publicasyncTask int FreeSqlAddUserAsync( )
{
using( vardbContext = newTestContext)
{
var(myDbContext, fsql) = GetDbContext(dbContext);
varguid = Guid.NewGuid.ToString;
varuser = newUser
{
Id = guid,
Name = $"fsql- {guid.Substring( 0, 5)} "
};
// fsql.Insert(user).AsTable("User").ExecuteAffrowsAsync;
returnawaitfsql.Insert(user).ExecuteAffrowsAsync;
}
}
///summary
///反射獲取信息,并構建 FreeSql
////summary
///param name="dbContext"/param
///returns/returns
public(DbContext dbContext, IFreeSql fsql) GetDbContext(DbContext dbContext)
{
/*
((EQuality.Framework.Dal.EFDbContext)_IDbContext).ConnStr
((Microsoft.EntityFrameworkCore.DbContext)ss).Database.ProviderName
*/
//- Database
// {Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade}
// Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade
vardbFacade = dbContext.GetPropertyDatabaseFacade( "Database");
stringdbType = dbFacade.ProviderName; // db 類型
stringconnStr = dbContext.Database.GetConnectionString; // 獲取 db 連接字符串
IFreeSql fsql = FreeSqlHelper.GetInstance.FreeBuilder(dbType, connStr); // 單例構造器構建 IFreeSql 對象
return(dbContext, fsql);
}
此處項目【 Jeff.Mes.EntityFrameworkCore 】中 TestContext.cs 類已經(jīng)完成兩種 orm 模式下新增 User 信息的操作,分別是:
AddUserAsync ,【 EF Core 模式】添加用戶測試;
FreeSqlAddUserAsync ,【 FreeSql 模式】添加用戶測試;
AddUserAsync ,【 EF Core 模式】添加用戶測試;
FreeSqlAddUserAsync ,【 FreeSql 模式】添加用戶測試;
到這里我們就可以使用 FreeSql 無縫替換 EF Core 的操作,同時也保留了 EF Core 模式的玩法,小伙伴們又可以繼續(xù)愉快的玩耍了喲。
測試 orm 兩種模式下的操作 添加 User 用戶信息
新增控制臺項目【 Jeff.Mes.EntityFrameworkCore.Test 】,項目引用【 Jeff.Mes.EntityFrameworkCore 】,添加如下代碼:
namespaceJeff.Mes.EntityFrameworkCore.Test;
internalclassProgram
{
staticasyncTask Main( string[] args )
{
Console.WriteLine( "Hello, EF Core FreeSQL!");
vartest = newTestContext;
intrcount1 = awaittest.AddUserAsync;
stringinfo1 = rcount1 0? "User 信息添加成功": "User 信息添加失敗";
Console.WriteLine( $"efcore 模式: {info1}" );
intrcount2 = awaittest.FreeSqlAddUserAsync;
stringinfo2 = rcount2 0? "User 信息添加成功": "User 信息添加失敗";
Console.WriteLine( $"fsql 模式: {info2}" );
Console.ReadKey;
}
}
使用 vs 【工具 = 連接到數(shù)據(jù)庫】測試數(shù)據(jù)庫連接是否能正常通信訪問,測試如下:
vs 連接數(shù)據(jù)庫
啟動控制臺,執(zhí)行代碼,輸出如下信息:
Hello, EF Core FreeSQL!
efcore 模式:User 信息添加成功
fsql 模式:User 信息添加成功
控制臺測試
使用數(shù)據(jù)庫客戶端工具 DBeaver 查看:
user 表數(shù)據(jù) FreeSql 查詢 User 用戶信息
使用 FreeSQL 查詢 User 表信息:
///summary
///【FreeSql 模式】查詢用戶信息
////summary
///returns/returns
publicasyncTaskListUser FreeSqlGetUserAsync
{
using( vardbContext = newTestContext)
{
var(myDbContext, fsql) = GetDbContext(dbContext);
returnawaitfsql.SelectUser.ToListAsync;
}
}
控制臺 Main 函數(shù)中調用 FreeSqlGetUserAsync 方法:
fsql 查詢 user 信息
關于 FreeSql 更多信息,請查看相關文檔
FreeSql 官方文檔,https://freesql.net/
FreeSql 博客文檔,https://www.cnblogs.com/FreeSql/p/11531300.html
FreeSql 官方文檔,https://freesql.net/
FreeSql 博客文檔,https://www.cnblogs.com/FreeSql/p/11531300.html
總結
在使用 EF Core 作為默認的 ORM 工具操作數(shù)據(jù)庫時,項目中我們或許只能接觸到 DbContext 對象,沒法直接獲取 db 數(shù)據(jù)庫連接信息,假如有小伙伴想接入 FreeSQL 繼續(xù)使用熟悉的模式,那該怎么辦呢?此時我們可以這樣操作,為了不影響原有項目結構的操作,又想接入 FreeSQL 的小伙伴們,通過上面的方式我們就可以使用 FreeSQL 無縫替換 EF Core 。
其實接入 FreeSQL 的方式很簡單,只需具備兩點條件即可,首先就是 有效的 db 連接字符串【 dbContext.Database.GetConnectionString 】,其次就是獲取對應的 數(shù)據(jù)庫類型【 dbFacade.ProviderName 】。
掃描二維碼推送至手機訪問。
版權聲明:本文由飛速云SEO網(wǎng)絡優(yōu)化推廣發(fā)布,如需轉載請注明出處。