作者 Mr-zhong
程式碼改變世界....
Fast Framework 基於NET6.0 封裝的輕量級 ORM 框架 支援多種資料庫 SqlServer Oracle MySql PostgreSql Sqlite
優點: 體積小、原生支援微軟特性、流暢API、使用簡單、效能高、模型資料繫結採用 Expression、強大的表示式解析、支援多種子查詢可實現較為複雜查詢、原始碼可讀性強、支援AOT 編譯。
缺點:目前僅支援Db Frist
ps:此版本不再支援動態切換資料庫驅動,DbOptions 依舊支援熱過載
1.不要在方法里根據名稱去動態獲取方法資訊
2.不要使用Emit
3.不要使用dynamic 關鍵字 使用object 代替
4.設定 rd.xml 檔案
5.Json序列化不要使用 System.Text.Json 可以使用 Newtonsoft.Json 替代
6.不要在同一個解決方案去依賴使用反射專案的類庫,需編譯後單獨參照,否則編譯有問題
名稱 | 說明 |
---|---|
Fast.Framework | ORM |
Fast.Framework.Logging | 檔案紀錄檔 (擴充套件專案可不使用) |
Fast.Framework.DependencyInjection | 依賴注入 (擴充套件專案可不使用) 不支援AOT |
Fast.Framework.Test | 控制檯測試專案 |
Fast.Framework.UnitTest | 單元測試專案 |
Fast.Framework.Web.Test | Web測試專案 |
Ado
IAdo ado = new AdoProvider(new DbOptions()
{
DbId = "1",
DbType = DbType.MySQL,
ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=3;max pool size=100;connect timeout=30;"
});
DbContext 支援多租戶
IDbContext db = new DbContext(new List<DbOptions>() {
new DbOptions()
{
DbId = "1",
DbType = DbType.MySQL,
ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=3;max pool size=100;connect timeout=30;"
}});
DbOptions Json檔案設定格式
"DbOptions": [
{
"DbId": 1,
"DbType": "SQLServer",
"ConnectionStrings": "server=localhost;database=Test;user=sa;pwd=123456789;min pool size=3;max pool size=100;connect timeout=120;"
}]
主從分離(讀寫分離)設定
"DbOptions": [
{
"DbId": 2,
"DbType": "MySQL",
"IsDefault": true,
"ConnectionStrings": "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;AllowLoadLocalInfile=true;",
"UseMasterSlaveSeparation": true,//使用主從分離 注意所有事務將強制走主庫
"SlaveItems": [
{
"Weight": 1,//注意多個從庫 必須設定權重且總權重>從庫數
"ConnectionStrings": "server=localhost;database=Test1;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;AllowLoadLocalInfile=true;",
"Description": "從庫連線設定"
},
{
"Weight": 2,
"ConnectionStrings": "server=localhost;database=Test2;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;AllowLoadLocalInfile=true;",
"Description": "從庫連線設定"
}
],
"Description": "主庫連線設定"
}
]
Asp.net Core 依賴注入
// 註冊服務
var builder = WebApplication.CreateBuilder(args);
// 新增資料庫上下文
builder.Services.AddFastDbContext();
// 從Json組態檔載入資料庫選項
builder.Services.Configure<List<DbOptions>>(builder.Configuration.GetSection("DbOptions"));
// 產品服務類 通過構造方法注入
public class ProductService
{
/// <summary>
/// 資料庫
/// </summary>
private readonly IDbContext db;
/// <summary>
/// 構造方法
/// </summary>
/// <param name="db">資料庫</param>
public ProductService(IDbContext db)
{
this.db = db;
}
}
實體物件插入
var product = new Product()
{
ProductCode = "1001",
ProductName = "測試商品1"
};
var result = db.Insert(product).Exceute();
實體物件插入並返回自增ID 僅支援 SQLServer MySQL SQLite
var product = new Product()
{
ProductCode = "1001",
ProductName = "測試產品1"
};
var result = db.Insert(product).ExceuteReturnIdentity();
實體物件列表插入
var list = new List<Product>();
for (int i = 0; i < 2100; i++)
{
list.Add(new Product()
{
ProductCode = $"編號{i + 1}",
ProductName = $"名稱{i + 1}"
});
}
var result = db.Insert(list).Exceute();
匿名物件插入
var obj = new
{
ProductCode = "1001",
ProductName = "測試商品1"
};
//注意:需要使用As方法顯示指定表名稱
var result = db.Insert(obj).As("Product").Exceute();
匿名物件列表插入
var list = new List<object>();
for (int i = 0; i < 2100; i++)
{
list.Add(new
{
ProductCode = $"編號{i + 1}",
ProductName = $"名稱{i + 1}"
});
}
//注意:需要使用As方法顯示指定表名稱
var result = db.Insert(list).As("Product").Exceute();
字典插入
var product = new Dictionary<string, object>()
{
{"ProductCode","1001"},
{ "ProductName","測試商品1"}
};
var result = db.Insert(product).As("Product").Exceute();
字典列表插入
var list = new List<Dictionary<string, object>>();
for (int i = 0; i < 2100; i++)
{
list.Add(new Dictionary<string, object>()
{
{"ProductCode","1001"},
{ "ProductName","測試商品1"}
});
}
var result = db.Insert(list).As("Product").Exceute();
實體物件刪除
var product = new Product()
{
ProductId = 1,
ProductCode = "1001",
ProductName = "測試商品1"
};
var result = db.Delete(product).Exceute();
實體物件列表刪除
var list = new List<Product>();
for (int i = 0; i < 2100; i++)
{
list.Add(new Product()
{
ProductCode = $"編號{i + 1}",
ProductName = $"名稱{i + 1}"
});
}
var result = db.Delete(list).Exceute();
無條件刪除
var result = db.Delete<Product>().Exceute();
條件刪除
var result = await db.Delete<Product>().Where(w => w.ProductId == 1).ExceuteAsync();
邏輯刪除
/*
可用特性標記邏輯刪除列 僅支援 int bool datetime 型別,其它型別不合適
/// <summary>
/// 刪除標記
/// </summary>
[Logic]
public bool DeleteMark { get; set; }
*/
//額外設定其它屬性值,使用SetColumns方法前需先使用IsLogic方法
//型別邏輯刪除
var result1 = db.Delete<Product>().IsLogic().SetColumns(c => new Product()
{
ModifyTime = DateTime.Now
}).Where(w => w.ProductId == 1).Exceute();
//物件邏輯刪除
var result2 = db.Delete(new Product() { ProductId = 1 }).IsLogic().SetColumns(c => new Product()
{
ModifyTime = DateTime.Now
}).Exceute();
//特殊邏輯刪除(不想建實體類可以用該方式)
var result3 = db.Delete<object>().As("Product").IsLogic().SetColumns(c => new
{
ModifyTime = DateTime.Now
}).Exceute();
特殊刪除
//特殊用法 如需單個條件或多個可搭配 Where或WhereColumns方法
var result = await db.Delete<object>().As("Product").ExceuteAsync();
Console.WriteLine($"無實體刪除 受影響行數 {result}");
實體物件更新
var product = new Product()
{
ProductId = 1,
ProductCode = "1001",
ProductName = "測試商品1"
};
//注意:標記KeyAuttribute特性屬性或使用Where條件,為了安全起見全表更新將必須使用Where方法
var result = db.Update(product).Exceute();
指定列更新
var result = db.Update<Product>(new Product() { ProductCode = "1001", ProductName = "1002" }).UpdateColumns(c=> new { c.ProductCode , c.ProductName }).Exceute();
// 推薦使用表示式 c=>new {} 好處更改屬性名稱可以同步修改
忽略列更新
var result = db.Update<Product>(new Product() { ProductCode = "1001", ProductName = "1002" }).IgnoreColumns(c=> new { c.Custom1 }).Exceute();
// 同上使用方法一樣
實體物件列表更新
var list = new List<Product>();
for (int i = 0; i < 2022; i++)
{
list.Add(new Product()
{
ProductCode = $"編號{i + 1}",
ProductName = $"名稱{i + 1}"
});
}
//注意:標記KeyAuttribute特性屬性或使用WhereColumns方法指定更新條件列
var result = db.Update(list).Exceute();
匿名物件更新
var obj = new
{
ProductId = 1,
ProductCode = "1001",
ProductName = "測試商品1"
};
//注意:需要顯示指定表名稱 以及更新條件 使用 Where或者WhereColumns方法均可
var result = db.Update(obj).As("product").WhereColumns("ProductId").Exceute();
匿名物件列表更新
var list = new List<object>();
for (int i = 0; i < 2022; i++)
{
list.Add(new
{
ProductId = i + 1,
ProductCode = $"編號{i + 1}",
ProductName = $"名稱{i + 1}"
});
}
//由於是匿名物件需要顯示指定表名稱,使用WhereColumns方法指定更新條件列
var result = db.Update(list).As("Product").WhereColumns("ProductId").Exceute();
字典更新
var product = new Dictionary<string, object>()
{
{ "ProductId",1},
{"ProductCode","1001"},
{ "ProductName","測試商品1"}
};
var result = db.Update(product).As("Product").WhereColumns("ProductId").Exceute();
字典列表更新
var list = new List<Dictionary<string, object>>();
for (int i = 0; i < 2022; i++)
{
list.Add(new Dictionary<string, object>()
{
{ "ProductId",i+1},
{"ProductCode",$"更新編號:{i+1}"},
{ "ProductName",$"更新商品:{i + 1}"}
});
}
var result = db.Update(list).As("Product").WhereColumns("ProductId").Exceute();
設定列更新
// 設定列更新
db.Update<Product>().SetColumns(c => new Product()
{
ProductCode = "1001",
ProductName = "測試產品1"
}).Where(w => w.ProductId == 1).Exceute();
指定條件更新
var product = new Product()
{
ProductId = 1,
ProductCode = "1001",
ProductName = "測試商品1"
};
var result = db.Update(product).Where(p => p.ProductId == 100).Exceute();
Console.WriteLine($"表示式更新 受影響行數 {result}");
並行更新 樂觀鎖-版本控制
//注意:僅支援非列表更新 版本列資料型別僅支援 object、string、Guid 時間型別存在精度丟失所以不做支援
var obj = db.Query<Product>().Where(w => w.ProductId == 1).Frist();
obj.Custom1 = "測試版本控制修改";
//引數為 true 更新失敗將丟擲異常
var result = db.Update(obj).ExceuteWithOptLock(true);
單一查詢
var data = db.Query<Product>().First();
列表查詢
var data = db.Query<Product>().ToList();
返回單個字典
var data = db.Query<Product>().ToDictionary();
返回字典列表
var data = db.Query<Product>().ToDictionaryList();
分頁查詢
//分頁查詢不返回總數
var data = db.Query<Product>().ToPageList(1,100);
//分頁查詢返回總數
var total = 0;//定義總數變數
var data = db.Query<Product>().ToPageList(1, 1, ref total);
Console.WriteLine($"總數:{total}");
計數查詢
var data = db.Query<Product>().Count();
任何查詢
var data = db.Query<Product>().Any();
條件查詢
var data = db.Query<Product>().Where(w => w.ProductId == 1).ToList;
Like 查詢
var data = db.Query<Product>().Where(w => w.ProductName.StartsWith("左模糊") || w.ProductName.EndsWith("右模糊") || w.ProductName.Contains("全模糊")).ToList();
Not Like查詢
var data = db.Query<Product>().Where(w => !w.ProductName.StartsWith("左模糊") || !w.ProductName.EndsWith("右模糊") || !w.ProductName.Contains("全模糊")).ToList();
Select查詢 (選擇欄位)
var data = db.Query<Product>().Select(s => new
{
s.ProductId,
s.ProductName
}).ToList();
Select查詢 (Case When)
var data = db.Query<Product>().Select(s => new
{
CaseTest1 = SqlFunc.Case(s.Custom1).When("1").Then("xx1").When("2").Then("xx2").Else("xx3").End(),
CaseTest2 = SqlFunc.CaseWhen<string>(s.Custom1 == "1").Then("xx1").When(s.Custom1 == "2").Then("xx2").Else("xx3").End()
}).ToList();
分組查詢
var data = db.Query<Product>().GroupBy(s => new
{
s.ProductId,
s.ProductName
}).ToList();
分組聚合查詢
var sql = db.Query<Order>().InnerJoin<OrderDetail>((a, b) => a.OrderId == b.OrderId).GroupBy((a, b) => new
{
a.OrderCode
}).Select((a, b) => new
{
a.OrderCode,
Sum_Qty = SqlFunc.Sum(b.Qty)//支援巢狀
}).ToList();
排序查詢
var data = db.Query<Product>().OrderBy(s => new
{
s.CreateTime
}).ToList();
//這是多個欄位排序使用方法 還有其它過載方法
Having查詢
var data = db.Query<Product>().GroupBy(s => new
{
s.ProductId,
s.ProductName
}).Having(s => SqlFunc.Count(s.ProductId) > 1).ToList();
//必須先使用GroupBy方法 懂得都懂
聯表查詢
var data = db.Query<Product>().LeftJoin<Class1>((a, b) => a.ProductId == b.ProductId).ToList();
// 右連線 RightJoin 內連線 InnerJoin 全連線 FullJoin
聯合查詢
var query1 = db.Query<Product>();
var query2 = db.Query<Product>();
db.Union(query1, query2);//聯合
db.UnionAll(query1, query2);//全聯合
//執行查詢呼叫Toxx方法
導航查詢 (支援無限層級)
/// <summary>
/// 類別
/// </summary>
public class Category
{
/// <summary>
/// 類別ID
/// </summary>
[Key]
public int CategoryId { get; set; }
/// <summary>
/// 類別名稱
/// </summary>
public string CategoryName { get; set; }
/// <summary>
/// 產品 Navigate MainName和ChildName 可不顯示指定,會自動查詢主鍵匹配或ID為結尾的屬性
/// </summary>
[Navigate(MainName = nameof(CategoryId), ChildName = nameof(Product.CategoryId))]
public IEnumerable<Product> Products { get; set; }
}
var data = db.Query<Category>()
.Include(i => i.Products)
.ToList();
查詢並插入 僅支援同範例的資料庫 跨庫 個人還是建議 用事務分開寫查詢和插入
//方式1
var result1 = db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
{
s.ProductCode,
s.ProductName
}).Insert<Product>(p => new
{
p.ProductCode,
p.ProductName
});
//方式2
var result2 = db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
{
s.ProductCode,
s.ProductName
}).Insert("表名稱 同範例不同庫 可以使用 db.資料庫名稱.表名稱 ", "列名稱1", "列名稱2");
//方式3 需要注意同方式2 一樣
var result3 = db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
{
s.ProductCode,
s.ProductName
}).Insert("表名稱 同範例不同庫 可以使用 db.資料庫名稱.表名稱 ", new List<string>() { "列名稱1" });
In查詢
var data1 = db.Query<Product>().Where(w => new List<string>(){"1001", "1002"}.Contains(w.ProductCode)).ToList();
Select巢狀查詢和子查詢
var data1 = db.Query<Product>().Select(s => new
{
XX = db.Query<Product>().Select(s => 1).First()//需呼叫返回結果的方法 否則無法解析
}).First();
//進價用法,下面範例方法的過載均支援
var count = 0;
var refAsync = new RefAsync<int>();
var query = db.Query<Product>().Select(s => new
{
WithAttr_First = db.QueryWithAttr<Product>().First(),
WithAttr_FirstAsync = db.QueryWithAttr<Product>().FirstAsync(),
WithAttr_ToList = db.QueryWithAttr<Product>().ToList(),
WithAttr_ToListAsync = db.QueryWithAttr<Product>().ToListAsync(),
First_1 = db.Query<Category>().Select(s => 1).First(),//解析成Sql
First = db.Query<Category>().First(),
FirstAsync = db.Query<Category>().FirstAsync(),
ToArray = db.Query<Category>().ToArray(),
ToArrayAsync = db.Query<Category>().ToArrayAsync(),
ToList = db.Query<Category>().ToList(),
ToListAsync = db.Query<Category>().ToListAsync(),
ToPageList = db.Query<Category>().ToPageList(1, 10),
ToPageListAsync = db.Query<Category>().ToPageListAsync(1, 10),
ToPageList_Count = db.Query<Category>().ToPageList(1, 10, ref count),
ToPageListAsync_Count = db.Query<Category>().ToPageListAsync(1, 10, refAsync),
ToDictionary = db.Query<Category>().ToDictionary(),
ToDictionaryAsync = db.Query<Category>().ToDictionaryAsync(),
ToDictionaryList = db.Query<Category>().ToDictionaryList(),
ToDictionaryListAsync = db.Query<Category>().ToDictionaryListAsync(),
ToDictionaryPageList = db.Query<Category>().ToDictionaryPageList(1, 10),
ToDictionaryPageListAsync = db.Query<Category>().ToDictionaryPageListAsync(1, 10),
ToDictionaryPageList_Count = db.Query<Category>().ToDictionaryPageList(1, 10, ref count),
ToDictionaryPageListAsync_Count = db.Query<Category>().ToDictionaryPageListAsync(1, 10, refAsync),
ToDataTable = db.Query<Category>().ToDataTable(),
ToDataTableAsync = db.Query<Category>().ToDataTableAsync(),
Max = db.Query<Category>().Max(a => a.CategoryId),//解析成Sql
MaxAsync = db.Query<Category>().MaxAsync(a => a.CategoryId),
Min = db.Query<Category>().Min(a => a.CategoryId),//解析成Sql
MinAsync = db.Query<Category>().MinAsync(a => a.CategoryId),
Count = db.Query<Category>().Count(),//解析成Sql
CountAsync = db.Query<Category>().CountAsync(),
Sum = db.Query<Category>().Sum(s => s.CategoryId),//解析成Sql
SumAsync = db.Query<Category>().SumAsync(s => s.CategoryId),
Avg = db.Query<Category>().Avg(s => s.CategoryId),//解析成Sql
AvgAsync = db.Query<Category>().AvgAsync(s => s.CategoryId)
});
var data2= query.First();
From子查詢
var subQuery2 = db.Query<Product>().Select(s=>new
{
s.ProductId,
s.CategoryId,
s.ProductCode,
s.ProductName,
s.DeleteMark
});
var data = db.Query(subQuery2).ToList();
Join子查詢
var subQuery1 = db.Query<Product>().Select(s => new
{
s.ProductId,
s.CategoryId,
s.ProductCode,
s.ProductName,
s.DeleteMark
});
var data = db.Query<Category>().InnerJoin(subQuery1, (a, b) => a.CategoryId == b.CategoryId).ToList();
Include查詢
// 聯表條件 預設優先匹配主鍵 其次帶有ID結尾的名稱
var data = db.Query<Category>().Include(i => i.Products).ToList();
Exists查詢
var data = db.Query<Product>()
.Where(w => db.Query<Product>().WhereIF(!string.IsNullOrWhiteSpace("測試"), a => a.ProductId == 1).Select(s => 1).Any())
.Select(s => new
{
s.ProductId,
s.ProductCode
}).ToList();
查詢繫結欄位(注意 欄位必須是公開的,否則繫結外部無法存取,沒有意義)
//當某些欄位需要參與計算並且不返回前端時推薦用欄位繫結,無需從A實體轉換到B實體,強烈推薦此方式
var data = db.Query<Product>().Select(s => new Product()
{
_xx = s.ProductName
}).First();
動態表示式 名稱空間 Fast.Framework.Utils
var ex = DynamicWhereExp.Create<Product>().AndIF(1 == 1, a => a.DeleteMark == true).Build();
var data = db.Query<Product>().Where(ex).ToList();
Sql函數 自定義函數 需引入名稱空間 Fast.Framework.Utils 使用SqlFunc類
SqlServer
型別轉換
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
ToString | CONVERT( VARCHAR(255),123) | 轉換 VARCHAR | 否 |
ToDateTime | CONVERT( DATETIME,‘2022-09-16’) | 轉換 DATETIME | 否 |
ToDecimal | CONVERT( DECIMAL(10,6),‘123’) | 轉換 DECIMAL | 否 |
ToDouble | CONVERT( NUMERIC(10,6),‘123’) | 轉換 NUMERIC | 否 |
ToSingle | CONVERT( FLOAT,‘123’) | 轉換 FLOAT | 否 |
ToInt32 | CONVERT( INT,‘123’) | 轉換 INT | 否 |
ToInt64 | CONVERT( BIGINT,‘123’) | 轉換 BIGINT | 否 |
ToBoolean | CONVERT( BIT,‘1’) | 轉換 BIT | 否 |
ToChar | CONVERT( CHAR(2),'x') | 轉換 CHAR | 否 |
聚合函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Max | MAX( a.[xx] ) | 最大值 | 是 |
Min | MIN( a.[xx] ) | 最小值 | 是 |
Count | COUNT( a.[xx] ) | 計數 | 是 |
Sum | SUM( a.[xx] ) | 合計 | 是 |
Avg | AVG( a.[xx] ) | 平均 | 是 |
數學函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Abs | ABS( a.[xx] ) | 絕對值 | 是 |
Round | ROUND( a.[xx] ,2 ) | 四捨五入 | 是 |
字串函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
StartsWith | LIKE 'xx'+‘%’ | 左模糊 | 否 |
EndsWith | LIKE ‘%’+'xx' | 右模糊 | 否 |
Contains | LIKE ‘%’+'xx'+‘%’ | 全模糊 | 否 |
SubString | SUBSTRING( 'xxxxxx' ,1,3) | 擷取 | 否 |
Replace | REPLACE( 'xxx','x','y') | 替換 | 否 |
Len | LEN( 'xxx' ) | 長度 | 是 |
TrimStart | LTRIM( ' xx ' ) | 修剪起始空格 | 否 |
TrimEnd | RTRIM( ' xx ' ) | 修剪末尾空格 | 否 |
ToUpper | UPPER( 'xx' ) | 大寫 | 否 |
ToLower | LOWER( 'xx' ) | 小寫 | 否 |
Concat | CONCAT(a.[xx1],a.[xx2]) | 字串拼接 | 否 |
Operation | [CreateTime] >= @Now_1 | 日期、數值、字串範圍比較 | 是 |
日期函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
DateDiff | DATEDIFF( DAY ,a.[xx],b.[xx]) | 日期相差 | 是 |
AddYears | DATEADD( YEAR,a.[xx],1 ) | 新增年份 | 否 |
AddMonths | DATEADD( MONTH,a.[xx],1 ) | 新增月份 | 否 |
AddDays | DATEADD( DAY,a.[xx],1 ) | 新增天數 | 否 |
AddHours | DATEADD( HOUR,a.[xx],1 ) | 新增時 | 否 |
AddMinutes | DATEADD( MINUTE,a.[xx],1 ) | 新增分 | 否 |
AddSeconds | DATEADD( SECOND,a.[xx],1 ) | 新增秒 | 否 |
AddMilliseconds | DATEADD( MILLISECOND,a.[xx],1 ) | 新增毫秒 | 否 |
Year | YEAR( a.[xx] ) | 獲取年份 | 是 |
Month | MONTH( a.[xx] ) | 獲取月份 | 是 |
Day | DAY( a.[xx] ) | 獲取天數 | 是 |
其它函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
NewGuid | NEWID() | 獲取GUID | 否 |
Equals | p.[ProductCode] = '123' | 比較 | 否 |
IsNull | ISNULL(a.[xx],0) | 是否為空 | 是 |
Case | CASE | case | 是 |
When | WHEN | when | 是 |
Then | THEN | then | 是 |
Else | ELSE | else | 是 |
End | END | end | 是 |
MySql
型別轉換
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
ToString | CAST( a.`xx` AS CHAR(510) ) | 轉換 CHAR(510) | 否 |
ToDateTime | CAST( a.`xx` AS DATETIME ) | 轉換 DATETIME | 否 |
ToDecimal | CAST( a.`xx` AS DECIMAL(10,6) ) | 轉換 DECIMAL(10,6) | 否 |
ToDouble | CAST( a.`xx` AS DECIMAL(10,6) ) | 轉換 DECIMAL(10,6) | 否 |
ToInt32 | CAST( a.`xx` AS DECIMAL(10) ) | 轉換 DECIMAL(10) | 否 |
ToInt64 | CAST( a.`xx` AS DECIMAL(19) ) | 轉換 DECIMAL(19) | 否 |
ToBoolean | CAST( a.`xx` AS UNSIGNED ) | 轉換 UNSIGNED | 否 |
ToChar | CAST( a.`xx` AS CHAR(2) ) | 轉換 CHAR(2) | 否 |
聚合函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Max | MAX( a.`xx` ) | 最大值 | 是 |
Min | MIN( a.`xx` ) | 最小值 | 是 |
Count | COUNT( a.`xx` ) | 計數 | 是 |
Sum | SUM( a.`xx` ) | 合計 | 是 |
Avg | AVG( a.`xx` ) | 平均 | 是 |
數學函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Abs | ABS( a.`xx` ) | 絕對值 | 是 |
Round | ROUND( a.`xx` ,2 ) | 四捨五入 | 是 |
字串函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
StartsWith | LIKE CONCAT( 'xx','%' ) | 左模糊 | 否 |
EndsWith | LIKE CONCAT( '%','xx' ) | 右模糊 | 否 |
Contains | LIKE CONCAT( '%','xx','%' ) | 全模糊 | 否 |
SubString | SUBSTRING( 'xxxxxx' ,1,3 ) | 擷取 | 否 |
Replace | REPLACE( 'xxx','x','y' ) | 替換 | 否 |
Len | LEN( 'xxx' ) | 長度 | 是 |
Trim | TRIM( ' xx ' ) | 修剪空格 | 否 |
TrimStart | LTRIM( ' xx ' ) | 修剪起始空格 | 否 |
TrimEnd | RTRIM( ' xx ' ) | 修剪末尾空格 | 否 |
ToUpper | UPPER( 'xx' ) | 大寫 | 否 |
ToLower | LOWER( 'xx' ) | 小寫 | 否 |
Concat | CONCAT(a.`xx1`,a.`xx2`) | 字串拼接 | 否 |
Operation | `CreateTime` >= @Now_1 | 日期、數值、字串範圍比較 | 是 |
日期函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
DateDiff | DATEDIFF( a.`xx`,b.`xx` ) | 日期相差 返回相差天數 | 是 |
TimestampDiff | TIMESTAMPDIFF( DAY,a.`xx`,b.`xx` ) | 日期相差 指定時間單位 | 是 |
AddYears | DATE_ADD( a.`xx`,INTERVAL 1 YEAR ) | 新增年份 | 否 |
AddMonths | DATE_ADD( a.`xx`,INTERVAL 1 MONTH ) | 新增月份 | 否 |
AddDays | DATE_ADD( a.`xx`,INTERVAL 1 DAY ) | 新增天數 | 否 |
AddHours | DATE_ADD( a.`xx`,INTERVAL 1 HOUR ) | 新增時 | 否 |
AddMinutes | DATE_ADD( a.`xx`,INTERVAL 1 MINUTE ) | 新增分 | 否 |
AddSeconds | DATE_ADD( a.`xx`,INTERVAL 1 SECOND ) | 新增秒 | 否 |
AddMilliseconds | DATE_ADD( a.`xx`,INTERVAL 1 MINUTE_SECOND ) | 新增毫秒 | 否 |
Year | YEAR( a.`xx` ) | 獲取年份 | 是 |
Month | MONTH( a.`xx` ) | 獲取月份 | 是 |
Day | DAY( a.`xx` ) | 獲取天數 | 是 |
其它函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
NewGuid | UUID() | 獲取GUID | 否 |
Equals | p.`ProductCode` = '123' | 比較 | 否 |
IfNull | IFNULL( a.`xx`,0 ) | 如果為空 | 是 |
Case | CASE | case | 是 |
When | WHEN | when | 是 |
Then | THEN | then | 是 |
Else | ELSE | else | 是 |
End | END | end | 是 |
Oracle
型別轉換
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
ToString | CAST( a."xx" AS VARCHAR(255) ) | 轉換 VARCHAR | 否 |
ToDateTime | TO_TIMESTAMP( a."xx" ,'yyyy-MM-dd hh:mi:ss.ff') | 轉換 DATETIME | 否 |
ToDecimal | CAST( a."xx" AS DECIMAL(10,6) ) | 轉換 DECIMAL | 否 |
ToDouble | CAST( a."xx" AS NUMBER ) | 轉換 NUMBER | 否 |
ToSingle | CAST( a."xx" AS FLOAT ) | 轉換 FLOAT | 否 |
ToInt32 | CAST( a."xx" AS INT ) | 轉換 INT | 否 |
ToInt64 | CAST( a."xx" AS NUMBER ) | 轉換 NUMBER | 否 |
ToBoolean | CAST( a."xx" AS CHAR(1) ) | 轉換 CHAR | 否 |
ToChar | CAST( a."xx" AS CHAR(2) ) | 轉換 CHAR | 否 |
聚合函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Max | MAX( a."xx" ) | 最大值 | 是 |
Min | MIN( a."xx" ) | 最小值 | 是 |
Count | COUNT( a."xx" ) | 計數 | 是 |
Sum | SUM( a."xx" ) | 合計 | 是 |
Avg | AVG( a."xx" ) | 平均 | 是 |
數學函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Abs | ABS( a."xx" ) | 絕對值 | 是 |
Round | ROUND( a."xx" ,2 ) | 四捨五入 | 是 |
字串函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
StartsWith | LIKE CONCAT( 'xx','%' ) | 左模糊 | 否 |
EndsWith | LIKE CONCAT( '%','xx' ) | 右模糊 | 否 |
Contains | LIKE CONCAT( '%','xx','%' ) | 全模糊 | 否 |
SubString | SUBSTRING( 'xxxxxx' ,1,3) | 擷取 | 否 |
Replace | REPLACE( 'xxx','x','y') | 替換 | 否 |
Length | LENGTH( 'xxx' ) | 長度 | 是 |
TrimStart | LTRIM( ' xx ' ) | 修剪起始空格 | 否 |
TrimEnd | RTRIM( ' xx ' ) | 修剪末尾空格 | 否 |
ToUpper | UPPER( 'xx' ) | 大寫 | 否 |
ToLower | LOWER( 'xx' ) | 小寫 | 否 |
Concat | CONCAT(a."xx1",a."xx2") | 字串拼接 | 否 |
Operation | 」CreateTime「 >= @Now_1 | 日期、數值、字串範圍比較 | 是 |
日期函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Year | EXTRACT( YEAR FROM a."xx" ) | 獲取年份 | 是 |
Month | EXTRACT( MONTH FROM a."xx" ) | 獲取月份 | 是 |
Day | EXTRACT( DAY FROM a."xx" ) | 獲取天數 | 是 |
其它函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Equals | p."ProductCode" = '123' | 比較 | 否 |
Nvl | NVL( a."xx",0 ) | 空,預設 | 是 |
Case | CASE | case | 是 |
When | WHEN | when | 是 |
Then | THEN | then | 是 |
Else | ELSE | else | 是 |
End | END | end | 是 |
PostgreSql
型別轉換
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
ToString | a."xx"::VARCHAR(255) | 轉換 VARCHAR | 否 |
ToDateTime | a."xx"::TIMESTAMP | 轉換 TIMESTAMP | 否 |
ToDecimal | a."xx"::DECIMAL(10,6) | 轉換 DECIMAL | 否 |
ToDouble | a."xx"::NUMERIC(10,6) | 轉換 NUMERIC | 否 |
ToSingle | a."xx"::REAL | 轉換 REAL | 否 |
ToInt32 | a."xx"::INTEGER | 轉換 INT | 否 |
ToInt64 | a."xx"::BIGINT | 轉換 BIGINT | 否 |
ToBoolean | a."xx"::BOOLEAN | 轉換 BOOLEAN | 否 |
ToChar | a."xx"::CHAR(2) | 轉換 CHAR | 否 |
聚合函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Max | MAX( a."xx" ) | 最大值 | 是 |
Min | MIN( a."xx" ) | 最小值 | 是 |
Count | COUNT( a."xx" ) | 計數 | 是 |
Sum | SUM( a."xx" ) | 合計 | 是 |
Avg | AVG( a."xx" ) | 平均 | 是 |
數學函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Abs | ABS( a."xx" ) | 絕對值 | 是 |
Round | ROUND( a."xx" ,2 ) | 四捨五入 | 是 |
字串函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
StartsWith | LIKE CONCAT( '%','xx' ) | 左模糊 | 否 |
EndsWith | LIKE CONCAT( 'xx','%' ) | 右模糊 | 否 |
Contains | LIKE CONCAT( '%','xx','%' ) | 全模糊 | 否 |
SubString | SUBSTRING( 'xxxxxx' ,1,3 ) | 擷取 | 否 |
Replace | REPLACE( 'xxx','x','y' ) | 替換 | 否 |
Length | LENGTH( 'xxx' ) | 長度 | 是 |
Trim | TRIM( ' xx ' ) | 修剪空格 | 否 |
TrimStart | LTRIM( ' xx ' ) | 修剪起始空格 | 否 |
TrimEnd | RTRIM( ' xx ' ) | 修剪末尾空格 | 否 |
ToUpper | UPPER( 'xx' ) | 大寫 | 否 |
ToLower | LOWER( 'xx' ) | 小寫 | 否 |
Concat | CONCAT(a."xx1",a."xx2") | 字串拼接 | 否 |
Operation | 」CreateTime「 >= @Now_1 | 日期、數值、字串範圍比較 | 是 |
日期函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
AddYears | a."xx" + INTERVAL '1 YEAR' | 新增年份 | 否 |
AddMonths | a."xx" + INTERVAL '1 MONTH' | 新增月份 | 否 |
AddDays | a."xx" + INTERVAL '1 DAY' | 新增天數 | 否 |
AddHours | a."xx" + INTERVAL '1 HOUR' | 新增時 | 否 |
AddMinutes | a."xx" + INTERVAL '1 MINUTE' | 新增分 | 否 |
AddSeconds | a."xx" + INTERVAL '1 SECOND' | 新增秒 | 否 |
AddMilliseconds | a."xx" + INTERVAL '1 MINUTE_SECOND' | 新增毫秒 | 否 |
Year | YEAR( a."xx" ) | 獲取年份 | 是 |
Month | MONTH( a."xx" ) | 獲取月份 | 是 |
Day | DAY( a."xx" ) | 獲取天數 | 是 |
查詢函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
In | IN ( a."xx" ,'x1','x2','x3' ) | In查詢 | 是 |
NotIn | NOT IN ( a."xx" ,'x1','x2','x3' ) | Not In查詢 | 是 |
其它函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Equals | p.」ProductCode「 = '123' | 比較 | 否 |
Case | CASE | case | 是 |
When | WHEN | when | 是 |
Then | THEN | then | 是 |
Else | ELSE | else | 是 |
End | END | end | 是 |
Sqlite
型別轉換
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
ToString | CAST(a.[xx] AS TEXT ) | 轉換 TEXT | 否 |
ToDateTime | DATETIME( a.[xx] ) | 轉換 DateTime | 否 |
ToDecimal | CAST(a.[xx] AS DECIMAL(10,6) ) | 轉換 DECIMAL | 否 |
ToDouble | CAST(a.[xx] AS NUMERIC(10,6) ) | 轉換 NUMERIC | 否 |
ToSingle | CAST(a.[xx] AS FLOAT ) | 轉換 FLOAT | 否 |
ToInt32 | CAST(a.[xx] AS INTEGER ) | 轉換 INTEGER | 否 |
ToInt64 | CAST(a.[xx] AS BIGINT ) | 轉換 BIGINT | 否 |
ToBoolean | CAST(a.[xx] AS CHAR(1) ) | 轉換 CHAR | 否 |
ToChar | CAST(a.[xx] AS CHAR(2) ) | 轉換 CHAR | 否 |
聚合函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Max | MAX( a.[xx] ) | 最大值 | 是 |
Min | MIN( a.[xx] ) | 最小值 | 是 |
Count | COUNT( a.[xx] ) | 計數 | 是 |
Sum | SUM( a.[xx] ) | 合計 | 是 |
Avg | AVG( a.[xx] ) | 平均 | 是 |
數學函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Abs | ABS( a.[xx] ) | 絕對值 | 是 |
Round | ROUND( a.[xx] ,2 ) | 四捨五入 | 是 |
字串函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
StartsWith | LIKE 'xx'||'%' | 左模糊 | 否 |
EndsWith | LIKE '%'||'xx' | 否 | |
Contains | LIKE '%'||'xx'||'%' | 全模糊 | 否 |
SubString | SUBSTRING( 'xxxxxx' ,1,3 ) | 擷取 | 否 |
Replace | REPLACE( 'xxx','x','y' ) | 替換 | 否 |
Length | LENGTH( 'xxx' ) | 長度 | 是 |
Trim | TRIM( ' xx ' ) | 修剪空格 | 否 |
TrimStart | LTRIM( ' xx ' ) | 修剪起始空格 | 否 |
TrimEnd | RTRIM( ' xx ' ) | 修剪末尾空格 | 否 |
ToUpper | UPPER( 'xx' ) | 大寫 | 否 |
ToLower | LOWER( 'xx' ) | 小寫 | 否 |
Operation | [CreateTime] >= @Now_1 | 日期、數值、字串範圍比較 | 是 |
日期函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
AddYears | DATETIME( a.[xx],'1 YEAR' ) | 新增年份 | 否 |
AddMonths | DATETIME( a.[xx],'1 MONTH' ) | 新增月份 | 否 |
AddDays | DATETIME( a.[xx],'1 DAY' ) | 新增天數 | 否 |
AddHours | DATETIME( a.[xx],'1 HOUR' ) | 新增時 | 否 |
AddMinutes | DATETIME( a.[xx],'1 MINUTE' ) | 新增分 | 否 |
AddSeconds | DATETIME( a.[xx],'1 SECOND' ) | 新增秒 | 否 |
AddMilliseconds | DATETIME( a.[xx],'1 YEAR' ) | 新增毫秒 | 否 |
Year | STRFTIME( '%Y', a.[xx] ) | 獲取年份 | 是 |
Month | STRFTIME( '%m', a.[xx] ) | 獲取月份 | 是 |
Day | STRFTIME( '%j', a.[xx] ) | 獲取天數 | 是 |
其它函數
方法名稱 | 解析範例值 | 說明 | 自定義函數 |
---|---|---|---|
Equals | p.」ProductCode「 = '123' | 比較 | 否 |
Case | CASE | case | 是 |
When | WHEN | when | 是 |
Then | THEN | then | 是 |
Else | ELSE | else | 是 |
End | END | end | 是 |
新增自定義函數解析
//注意:只能擴充套件未實現的方法名稱 不能覆蓋原有的實現
Models.DbType.MySQL.AddSqlFunc("方法名稱", (visit, method, sqlStack) =>
{
//解析邏輯
});
db.Aop.DbLog = (sql, dp) =>
{
Console.WriteLine($"執行Sql:{sql}");
if (dp != null)
{
foreach (var item in dp)
{
Console.WriteLine($"引數名稱:{item.ParameterName} 引數值:{item.ParameterValue}");
}
}
};
普通事務
try
{
db.Ado.BeginTran();//開啟事務
// 執行 CRUD
db.Ado.CommitTran();//提交事務
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
db.Ado.RollbackTran();//回滾事務
}
更大範圍的事務
try
{
db.BeginTran();//開啟事務
// 執行 CRUD
db.CommitTran();//提交事務
}
catch (Exception ex)
{
db.RollbackTran();//回滾事務
Console.WriteLine(ex.Message);
}
改變資料庫
//資料庫設定可從Json組態檔載入
IDbContext db = new DbContext(new List<DbOptions>() {
new DbOptions()
{
DbId = "1",
DbType = Models.DbType.SQLServer,
ConnectionStrings = "server=localhost;database=Test;user=sa;pwd=123456789;min pool size=0;max pool size=100;connect timeout=120;"
},
new DbOptions()
{
DbId = "2",
DbType = Models.DbType.MySQL,
ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;"
}});
db.ChangeDb("2");//切換到MySQL
/// <summary>
/// 產品
/// </summary>
[Table("ProductMain")]
public class Product
{
/// <summary>
/// 產品ID
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductId { get; set; }
/// <summary>
/// 產品編號
/// </summary>
[Column("ProductCode")]//不標記預設取當前屬性名稱
public string ProductCode { get; set; }
/// <summary>
/// 自定義1
/// </summary>
[NotMapped]
public string Custom1 { get; set; }
/// <summary>
/// 自定義2
/// </summary>
[Column(TypeName="Json")]//型別標記為Json格式物件 匿名物件屬性以及字典值型別 IsClass&&!type.Equals(typeof(string)) 將自動序列化成Json格式
public Category Custom2 { get; set; }
}
// 原始起步
// var conn = db.Ado.DbProviderFactory.CreateConnection();
// var cmd = conn.CreateCommand();
// 封裝的方法分別以Execute和Create開頭以及預處理 PrepareCommand 方法
// 該方法可以自動幫你處理執行的預操作,主要作用是程式碼複用。
// 當有非常複雜的查詢 ORM不能滿足需求的時候可以使用原生Ado滿足業務需求
// 構建資料集核心擴充套件方法 分別有 FirstBuild ListBuild DictionaryBuild DictionaryListBuild
var data = db.Ado.ExecuteReader(CommandType.Text, "select * from product", null).ListBuild<Product>();
註冊資料庫上下文和工作單元服務
var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
// 新增資料庫上下文服務
builder.Services.AddFastDbContext();
// 新增工作單元服務
builder.Services.AddUnitOfWork();
// 載入資料庫設定
builder.Services.Configure<List<DbOptions>>(configuration.GetSection("DbConfig"));
實際應用
/// <summary>
/// 工作單元
/// </summary>
private readonly IUnitOfWork unitOfWork;
/// <summary>
/// 構造方法
/// </summary>
/// <param name="unitOfWork">工作單元</param>
public UnitOfWorkTestService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
/// <summary>
/// 測試
/// </summary>
/// <returns></returns>
public string Test()
{
//unitOfWork 物件無需顯示使用using
var result1 = unitOfWork.Db.Insert(new Category()
{
CategoryName = "類別3"
}).Exceute();
var result2 = unitOfWork.Db.Insert(new Product()
{
ProductCode = "測試工作單元",
}).Exceute();
unitOfWork.Commit();
return "工作單元執行完成...";
}
批覆制 僅支援SqlServer Oracle MySql PostgreSql
var list = new List<Product>();
for (int j = 1; j <= 100000; j++)
{
list.Add(new Product()
{
CategoryId = 1,
ProductCode = $"測試編號_{Timestamp.CurrentTimestampSeconds()}_{j}",
ProductName = $"測試名稱_{Timestamp.CurrentTimestampSeconds()}_{j}",
CreateTime = DateTime.Now,
Custom1 = $"測試自定義1_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom2 = $"測試自定義2_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom3 = $"測試自定義3_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom4 = $"測試自定義4_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom5 = $"測試自定義5_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom6 = $"測試自定義6_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom7 = $"測試自定義7_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom8 = $"測試自定義8_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom9 = $"測試自定義9_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom10 = $"測試自定義10_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom11 = $"測試自定義11_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom12 = $"測試自定義12_{Timestamp.CurrentTimestampSeconds()}_{j}",
});
}
db.Fast<Product>().BulkCopy(list);
本文來自部落格園,作者:China-Mr-zhong,轉載請註明原文連結:https://www.cnblogs.com/China-Mr-zhong/p/17852177.html