针对DbConnection扩展读取Xml文件Sql语句,语法格式和遵循Ado.Net原生的Sql写法
本框架核心代码摘自Insql,Insql定位是ORM,可以完全独立的引入它。SqlXmlMapper定位于基于Xml文件Sql语句扩展。所以很多场景并不冲突。作者只是以为单独引入ORM有点过于笨重,所以基于Insql精简了一下核心操作。
笔者已将具体的使用文档放到了github中,可以下载SqlXmlMapper使用说明.docx进行详细的查看或查看源码了解相关使用。想了解详细的用法可以查看测试项目使用示例。
针对业务场景中复杂查询的情况,使用EF虽然可以满足实现功能但是无法保证sql语句的可预料性。所以引入了将复杂Sql查询语句的xml化,编写规则符合ado.net的编程习惯,使用也比较简单。
需要使用的项目中引入IServiceCollection扩展方法AddSqlXmlMapper,其中传递的参数为sqlxml所在的文件夹路径
IServiceCollection services = new ServiceCollection();
services.AddSqlXmlMapper("./SqlMapper");
支持传递多个xml文件夹路径
IServiceCollection services = new ServiceCollection();
services.AddSqlXmlMapper("./SqlMapper","./SqlMapper2","./SqlMapper3");
①Sql语句是存放到上文配置的xml文件夹中的(xml文件要在vs上配置为始终复制)。 ②Xml文件的名称必须以xml节点中insql type的值开头
<?xml version="1.0" encoding="utf-8" ?>
<insql type="CoreMysql.Program" >
<select id="GetStudentCount">
select Id,Name from Student
where Deleted=@Deleted
group by Id,Name
having <![CDATA[count(Name)>=@NameCount]]>
</select>
<select id="GetStudents">
select Id,Name from Student
<where>
Deleted=@Deleted
<if test="Name!=null">
and Name=@Name
</if>
</where>
</select>
</insql>
③目前支持多个xml共享一个命名空间type的形式,但是必须保证其中Type+SqlId组成Sql节点唯一标识
支持动态where和if判断,sql语句的形式和原生的ado.net写法保持一致即可 如果不需要使用动态条件判断的时候直接写sql语句即可
IServiceCollection services = new ServiceCollection();
services.AddSqlXmlMapper("./SqlMapper");
IServiceProvider serviceProvider = services.BuildServiceProvider();
using (StudentSystemContext studentContext = new StudentSystemContext())
{
studentContext.Database.Log = Console.Write;
var groupListResult = studentContext.Database.Connection.Query<Program, StudentGroupDo>(serviceProvider, "GetStudentCount", new { Deleted = 0, NameCount = 1 });
foreach (var item in groupListResult)
{
Console.WriteLine($"{item.Id} {item.Name}");
}
var studentResult = studentContext.Database.Connection.Query<Program, StudentGroupDo>(serviceProvider, "GetStudents", new { Deleted = 0 });
foreach (var item in studentResult)
{
Console.WriteLine($"GetStudents:{item.Id} {item.Name}");
}
studentResult = studentContext.Database.Connection.Query<Program, StudentGroupDo>(serviceProvider, "GetStudents", new { Deleted = 0, Name = "小A" });
foreach (var item in studentResult)
{
Console.WriteLine($"GetStudentsWithName:{item.Id} {item.Name}");
}
var groupResult = studentContext.SqlQuery<Program, StudentGroupDo>(serviceProvider, "GetStudentCount", new { Deleted = 0, NameCount = 1 });
foreach (var item in groupResult)
{
Console.WriteLine($"{item.Id} {item.Name}");
}
Console.WriteLine();
var studentResult2 = studentContext.SqlQuery<Program, StudentGroupDo>(serviceProvider, "GetStudents", new { Deleted = 0 });
foreach (var item in studentResult2)
{
Console.WriteLine($"GetStudents:{item.Id} {item.Name}");
}
Console.WriteLine();
studentResult2 = studentContext.SqlQuery<Program, StudentGroupDo>(serviceProvider, "GetStudents", new { Deleted = 0, Name = "小A" });
foreach (var item in studentResult2)
{
Console.WriteLine($"GetStudentsWithName:{item.Id} {item.Name}");
}
Console.WriteLine();
var grades = studentContext.SqlQuery<Grade>(serviceProvider, "CoreMysql.Program.Grade", "GetGrades", new { Deleted = 1, Ids = new[] { 1, 3 } });
foreach (var item in grades)
{
Console.WriteLine($"GetGrade:{item.Id} {item.Name}");
}
grades = studentContext.SqlQuery<Grade>(serviceProvider, "CoreMysql.Program.Grade", "GetGrades2", new { Deleted = 0 });
foreach (var item in grades)
{
Console.WriteLine($"GetGrade2:{item.Id} {item.Name}");
}
var stuGradeClasses = studentContext.SqlQuery<StudentGradeClassDo>(serviceProvider, "CoreMysql.Program.Grade", "GetGradeStudent", new { Deleted = 0, ClassId = 1, GradeId = 1 });
foreach (var item in stuGradeClasses)
{
Console.WriteLine(item);
}
}
详细用法和和介绍可参考SqlXmlMapper使用说明.docx。想了解详细的用法可以查看测试项目使用示例。
笔者在测试文件中写了一个关于EF查询的扩展示例DbContextExtensions.cs用于演示,具体使用方式如下 ①泛型第一个参数为命名空间即和xml里的声明的type保持一致,标识一组sql的标识 比如这里可以是我们项目中的某个具体的Repository ②泛型的第二个参数表示查询返回结果对应的实体类型 ③参数列表第一个表示IServiceProvider实例,第二个参数表示Sql的唯一标识Id,第三个参数表示要传递的参数查询条件 如果是在一个Repository中想查询别的Repository命名空间下的sql,但是并不像直接引入这个Repository类,可以直接通过参数传递命名空间