一、項目介紹
該項目內置單表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>();
}
}
