一、項目介紹
該項目內置單表linq操作,xml動態sql解析,詞法分析,類型映射等功能。
-
SqlMapper,用來處理sql與數據庫操作,它設計的目標是支持mysql,sqlserver,sqllite,pgsql等.
-
TypeMapper用於完成將數據庫的字段類型映射到C#類型,內部定義了類型轉換函數和轉換規則.
-
TypeConvert用於完成數據庫記錄到C#類型的轉換。通過IL動態創建IDataReader對象到C#實體類的轉換函數和將C#對象解構成Key-value的函數.
-
ExpressionContext是一個輕量的詞法分析器,用於將字符串表達式生成C#表達式,進而生成委托.
- XmlResovle用於解析xml配置,如果你的項目僅需要xml動態解析功能你完全可以下載我的源碼進行改進(它在github中開源),半自動意味着超高的性能
- https://github.com/1448376744/SqlBatis
二 、詞法分析器
該類型的實例是線程安全的,可復用的。它的設計及其簡單,功能也很有限,但是對於我們的需求足夠了. 它的實現邏輯如下:
var expr = "(Age!=null) && (Name=='zs')"; /** 1.通過正則匹配出每一個括號,因此你必須手動的給每個二元表達式加括號,它無法識別運算符的優先級. $1 = (Age!=null) $2 = (Name=='zs') $3 = $1 && $2 2.創建參數類型 Expression.Parameter(typeof(T), "p"); 3.逐個創建二元表達式 Expression.MakeUnary(ExpressionType.Convert, expr, type) ... */ var context = new ExpressionContext(); //Age必須是可以為null的類型:int? var result = context.Create<Student>("(Age != null) && (Name=='zs')"); var flag= result.Func(new Student { Age =(int?) 1, Name = "zs" }); /** 常見錯誤: 1. (Age != null) && Name=='zs'
缺少括號 2. public class Student{ public int Age{get;set;} public string Name {get;set;}}
Age必須是int?類型 */
ExpressionContext
var context = new ExpressionContext(); var result = context.Create<Student>("(Age!=null)&&(Name=='zs')"); var expr = result.LambdaExpression; Func<Student, bool> func = result.Func; var flag = func(new Student { Age = 1, Name = "zs" });
三、XML解析
<?xml version="1.0" encoding="utf-8" ?> <commands namespace="sutdent"> <!-- 框架只定義了if,variable,where等標簽 insert,select可以隨意,並沒有實際意義 --> <variable id="columns"> Id,Age,Name </variable> <select id="list-dynamic"> select ${columns} from student <where> <if test="Id!=null" value="id=@Id"/> </where> limit 0,1 </select> <insert id="add"> insert into student(name,age)values(@Name,@age) </insert> </commands>
//解析sql var resovle = new XmlResovle(); resovle.Load(@"E:\SqlBatis\SqlBatis.Test", "*.xml"); //普通sql var sql1 = resovle.Resolve("namespace.id"); //動態sql var sql2 = resovle.Resolve("namespace.id",new { Id=(int?)null,Age=2});
四、配置DbContext
方式1
public class MysqlDbConrext : DbContext { public IDbQuery<Student> Students { get => new DbQuery<Student>(this); } private static readonly IXmlResovle resovle; static MysqlDbConrext() {
//不要為每一個DbContext加載配置 resovle = new XmlResovle(); resovle.Load(@"E:\SqlBatis\SqlBatis.Test","*.xml"); } protected override void OnLogging(string message, object parameter = null, int? commandTimeout = null, CommandType? commandType = null) { } protected override DbContextBuilder OnConfiguring(DbContextBuilder builder) { ILoggerFactory factory = LoggerFactory.Create(b => { b.AddConsole(); b.AddDebug(); b.SetMinimumLevel(LogLevel.Debug); }); builder.Connection = new MySql.Data.MySqlClient.MySqlConnection("server=127.0.0.1;user id=root;password=1024;database=test;"); builder.XmlResovle = null; return builder; } public MysqlDbConrext() { Students = new DbQuery<Student>(this); } }
方式2
var db = new DbContext(new DbContextBuilder() { DbContextType=DbContextType.Mysql, ... });
五、XML+Linq
using (var db = new SqlDbContext()) { //linq var row = db.Students.Delete(); var (list, count) = db.Students .Page(1, 2) .SelectMany(); //dynamic var p = new { Id = (int?)null, Name = "zs" }; var dylist = db.Students .Where(a => a.Id == 1, p.Id != null) .Where(a => a.Name == p.Name, p.Name != null) .SelectMany(); //xml row = db.From("sutdent.add", new Student() { Age = 20, IsDelete = true, Name = "xml" }).ExecuteNonQuery(); //dynamic:注意由於內部會緩存表達式創建的委托,因此同一個動態的xml命令不能用不同的參數去獲取它 //建議如果獲取的xml命令是動態的,則應保證整個項目只有一次獲取的代碼,或者使用同一種參數類型 row = db.From("stutdent.list-dynamic", p).ExecuteNonQuery(); //多結果集查詢,xml方式同樣支持 using (var muti = db.ExecuteMultiQuery("select * from student;select count(1) from student;")) { //第一個結果集 var list = muti.GetList<Student>(); //第二個結果集 var count = muti.Get<int>(); } }