【前言】

  接上一篇《【原创】打造基于Dapper的数据访问层》,Dapper在应付多表自由关联、分组查询、匿名查询等应用场景时不免显得吃力,经常要手写SQL语句(或者用工具生成SQL配置文件)。试想一下,项目中整个DAL层都塞满了SQL语句,对于后期维护来说无异于天灾人祸,这个坑谁踩谁知道。本框架在API设计上最大程度地借鉴 EntityFramework 的写法,干净的实体,丝滑的增删改查,稳健的导航属性,另外还支持链式查询(点标记)、查询表达式、聚合查询等等。在实体映射转换层面,使用 Emit 来动态构建绑定指令,性能最大限度地接近原生水平。

【XFramework 亮点】

  1. 原生.NET语法,零学习成本
  2. 支持LINQ查询、拉姆达表达式
  3. 支持批量增删改查和多表关联更新
  4. 支持 SqlServer、MySql、Postgre、Oracle,.NET Core
  5. 最大亮点,真正支持一对一、一对多导航属性。这一点相信现有开源的ORM没几个敢说它支持的
  6. 实体字段类型不必与数据库的类型一致
  7. 支持临时表、表变量操作
  8. 提供原生ADO操作
  9. 其它更多亮点,用了你就会知道

【性能】  

  看看与EntityFramework的性能对比,机器配置不同跑出来的结果可能也不一样,仅供参考。需要特别说明的是EntityFramework是用了AsNoTracking的,不然有缓存的话就没有比较的意义了。
  扯个题外话,有些ORM说比EntityFramework快百分多少多少,看起来挺美实际上在我看来那是在扯淡,没有任何参考价值。限制实体字段类型必须与数据库的一致不说,甚至连导航属性这种最基本的功能都不支持,这不在同一个等级同一个体量上的东西非要扯在一起比谁快,确定要这么幽默吗?本人非常推崇开源,也很尊重致力于开源的同行,但是像这种行为就非常有必要出来打假一波了。

  

【功能说明】

1. 实体定义  

  1.1. 如果类有 TableAttribute,则用 TableAttribute 指定的名称做为表名,否则用类名称做为表名
  1.2. 实体的字段可以指定 ColumnAttribute 特性来说明实体字段与表字段的对应关系,删除/更新时如果传递的参数是一个实体,必须使用 [Column(IsKey = true)] 指定实体的主键
  1.3. ForeignKeyAttribute 指定外键,一对多外键时类型必须是 IList<T> 或者 List<T>
  1.4 ColumnAttribute.DataType 用来指定表字段类型。以SQLSERVER为例,System.String 默认对应 nvarchar 类型。若是varchar类型,需要指定[Column(DbType= DbType.AnsiString)]

         [Table(Name = "Bas_Client")]
public partial class Client
{
/// <summary>
/// 初始化 <see cref="Client"/> 类的新实例
/// </summary>
public Client()
{
this.CloudServerId = ;
this.Qty = ;
this.HookConstructor();
} /// <summary>
/// 初始化 <see cref="Client"/> 类的新实例
/// </summary>
public Client(Client model)
{
this.CloudServerId = ;
this.Qty = ;
this.HookConstructor();
} /// <summary>
/// clientid
/// </summary>
[Column(IsKey = true)]
public virtual int ClientId { get; set; } /// <summary>
/// clientcode
/// </summary>
public virtual string ClientCode { get; set; } /// <summary>
/// clientname
/// </summary>
public virtual string ClientName { get; set; } /// <summary>
/// cloudserverid
/// </summary>
[Column(Default = )]
public virtual int CloudServerId { get; set; } /// <summary>
/// activedate
/// </summary>
public virtual Nullable<DateTime> ActiveDate { get; set; } /// <summary>
/// qty
/// </summary>
[Column(Default = )]
public virtual int Qty { get; set; } /// <summary>
/// state
/// </summary>
public virtual byte State { get; set; } /// <summary>
/// remark
/// </summary>
[Column(Default = "'默认值'")]
public virtual string Remark { get; set; } [ForeignKey("CloudServerId")]
public virtual CloudServer CloudServer { get; set; } [ForeignKey("CloudServerId")]
public virtual CloudServer LocalServer { get; set; } [ForeignKey("ClientId")]
public virtual List<ClientAccount> Accounts { get; set; } /// <summary>
/// 构造函数勾子
/// </summary>
partial void HookConstructor();
}

2. 上下文定义  

 SQLSERVER:var context = new SqlDbContext(connString);
MySQL:var context = new MyMySqlDbContext(connString);
Postgre:var context = new NpgDbContext(connString);
Oracle:var context = new OracleDbContext(connString);

3. 匿名类型

 //// 匿名类
var guid = Guid.NewGuid();
var dynamicQuery =
from a in context.GetTable<TDemo>()
where a.DemoId <=
select new
{
DemoId = ,
DemoCode = a.DemoCode,
DemoName = a.DemoName,
DemoDateTime_Nullable = a.DemoDateTime_Nullable,
DemoDate = sDate,
DemoDateTime = sDate,
DemoDateTime2 = sDate_null,
DemoGuid = guid,
DemoEnum = Model.State.Complete, // 枚举类型支持
DemoEnum2 = Model.State.Executing,
};
var result0 = dynamicQuery.ToList(); // 点标记
dynamicQuery = context
.GetTable<TDemo>()
.Where(a => a.DemoId <= )
.Select(a => new
{
DemoId = ,
DemoCode = a.DemoCode,
DemoName = a.DemoName,
DemoDateTime_Nullable = a.DemoDateTime_Nullable,
DemoDate = sDate,
DemoDateTime = sDate,
DemoDateTime2 = sDate_null,
DemoGuid = Guid.NewGuid(),
DemoEnum = Model.State.Complete,
DemoEnum2 = Model.State.Executing
});
result0 = dynamicQuery.ToList();

4. 所有字段

  // Date,DateTime,DateTime2 支持
var query =
from a in context.GetTable<TDemo>()
where a.DemoId <= && a.DemoDate > sDate && a.DemoDateTime >= sDate && a.DemoDateTime2 > sDate
select a;
var result1 = query.ToList();
// 点标记
query = context
.GetTable<TDemo>()
.Where(a => a.DemoId <= && a.DemoDate > sDate && a.DemoDateTime >= sDate && a.DemoDateTime2 > sDate);
result1 = query.ToList();

5. 指定字段

 // 指定字段
query = from a in context.GetTable<TDemo>()
where a.DemoId <=
select new TDemo
{
DemoId = (int)a.DemoId,
DemoCode = (a.DemoCode ?? "N001"),
DemoName = a.DemoId.ToString(),
DemoDateTime_Nullable = a.DemoDateTime_Nullable,
DemoDate = sDate,
DemoDateTime = sDate,
DemoDateTime2 = sDate
};
result1 = query.ToList();
// 点标记
query = context
.GetTable<TDemo>()
.Where(a => a.DemoCode != a.DemoId.ToString() && a.DemoName != a.DemoId.ToString() && a.DemoChar == 'A' && a.DemoNChar == 'B')
.Select(a => new TDemo
{
DemoId = a.DemoId,
DemoCode = a.DemoName == "张三" ? "李四" : "王五",
DemoName = a.DemoCode == "张三" ? "李四" : "王五",
DemoChar = 'A',
DemoNChar = 'B',
DemoDateTime_Nullable = a.DemoDateTime_Nullable,
DemoDate = sDate,
DemoDateTime = sDate,
DemoDateTime2 = sDate
});
result1 = query.ToList();

6.构造函数

  用过 EntityFramework 的同学都知道,如果要通过构造函数的方式查询指定字段,除非老老实实重新定义一个新的实体,否则一个 “The entity or complex type cannot be constructed in a LINQ to Entities query“ 的异常马上给甩你脸上。XFramework 框架的这个用法,就是为了让你远离这会呼吸的痛!~

 // 构造函数
var query =
from a in context.GetTable<Model.Demo>()
where a.DemoId <=
select new Model.Demo(a);
var r1 = query.ToList();
//SQL=>
//SELECT
//t0.[DemoId] AS [DemoId],
//t0.[DemoCode] AS [DemoCode],
//t0.[DemoName] AS [DemoName],
//...
//FROM [Sys_Demo] t0
//WHERE t0.[DemoId] <= 10
query =
from a in context.GetTable<Model.Demo>()
where a.DemoId <=
select new Model.Demo(a.DemoId, a.DemoName);
r1 = query.ToList();

7. 分页查询

 // 分页查询
// 1.不是查询第一页的内容时,必须先OrderBy再分页,OFFSET ... Fetch Next 分页语句要求有 OrderBy
// 2.OrderBy表达式里边的参数必须跟query里边的变量名一致,如此例里的 a。SQL解析时根据此变更生成表别名
query = from a in context.GetTable<TDemo>()
orderby a.DemoCode
select a;
query = query.Skip().Take();
result1 = query.ToList();
// 点标记
query = context
.GetTable<TDemo>()
.OrderBy(a => a.DemoCode)
.Skip()
.Take();
result1 = query.ToList();

8. 过滤条件

 // 过滤条件
query = from a in context.GetTable<TDemo>()
where a.DemoName == "D0000002" || a.DemoCode == "D0000002"
select a;
result1 = query.ToList();
// 点标记
query = context.GetTable<TDemo>().Where(a => a.DemoName == "D0000002" || a.DemoCode == "D0000002");
result1 = query.ToList();
query = context.GetTable<TDemo>().Where(a => a.DemoName.Contains(""));
result1 = query.ToList();
query = context.GetTable<TDemo>().Where(a => a.DemoCode.StartsWith("Code000036"));
result1 = query.ToList();
query = context.GetTable<TDemo>().Where(a => a.DemoCode.EndsWith(""));
result1 = query.ToList();

9. 更多条件

 // 支持的查询条件
// 区分 nvarchar,varchar,date,datetime,datetime2 字段类型
// 支持的字符串操作=> Trim | TrimStart | TrimEnd | ToString | Length
int m_byte = ;
Model.State state = Model.State.Complete;
query = from a in context.GetTable<TDemo>()
where
a.DemoCode == "" &&
a.DemoName == "" &&
a.DemoCode.Contains("TAN") && // LIKE '%%'
a.DemoName.Contains("TAN") && // LIKE '%%'
a.DemoCode.StartsWith("TAN") && // LIKE 'K%'
a.DemoCode.EndsWith("TAN") && // LIKE '%K'
a.DemoCode.Length == && // LENGTH
a.DemoCode.TrimStart() == "TF" &&
a.DemoCode.TrimEnd() == "TF" &&
a.DemoCode.TrimEnd() == "TF" &&
a.DemoCode.Substring() == "TF" &&
a.DemoDate == DateTime.Now &&
a.DemoDateTime == DateTime.Now &&
a.DemoDateTime2 == DateTime.Now &&
a.DemoName == (
a.DemoDateTime_Nullable == null ? "NULL" : "NOT NULL") && // 三元表达式
a.DemoName == (a.DemoName ?? a.DemoCode) && // 二元表达式
new[] { , , }.Contains(a.DemoId) && // IN(1,2,3)
new List<int> { , , }.Contains(a.DemoId) && // IN(1,2,3)
new List<int>(_demoIdList).Contains(a.DemoId) && // IN(1,2,3)
a.DemoId == new List<int> { , , }[] && // IN(1,2,3)
_demoIdList.Contains(a.DemoId) && // IN(1,2,3)
a.DemoName == _demoName &&
a.DemoCode == (a.DemoCode ?? "CODE") &&
new List<string> { "A", "B", "C" }.Contains(a.DemoCode) &&
a.DemoByte == (byte)m_byte &&
a.DemoByte == (byte)Model.State.Complete ||
a.DemoInt == (int)Model.State.Complete ||
a.DemoInt == (int)state ||
(a.DemoName == "STATE" && a.DemoName == "REMARK")// OR 查询
select a;
result1 = query.ToList();

10. DataTable和DataSet

 // DataTable
query = from a in context.GetTable<TDemo>()
orderby a.DemoCode
select a;
query = query.Take();
var result3 = context.Database.ExecuteDataTable(query); // DataSet
var define = query.Resolve();
List<DbCommandDefinition> sqlList = new List<DbCommandDefinition> { define, define, define };
var result4 = context.Database.ExecuteDataSet(sqlList);

11. 内联查询

 // INNER JOIN
var query =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
where a.ClientId >
select a;
var result = query.ToList();
// 点标记
query = context
.GetTable<Model.Client>()
.Join(context.GetTable<Model.CloudServer>(), a => a.CloudServerId, b => b.CloudServerId, (a, b) => a)
.Where(a => a.ClientId > );
result = query.ToList();

12. 左联查询

注意看第二个左关联,使用常量作为关联键,翻译出来的SQL语句大概是这样的:

SELECT ***
FROM [Bas_Client] t0
LEFT JOIN [Sys_CloudServer] t1 ON t0.[CloudServerId] = t1.[CloudServerId] AND N'567' = t1.[CloudServerCode]
WHERE t1.[CloudServerName] IS NOT NULL

有没有看到熟悉的味道,兄dei?

 // LEFT JOIN
query =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId into u_b
from b in u_b.DefaultIfEmpty()
select a;
query = query.Where(a => a.CloudServer.CloudServerName != null);
result = query.ToList(); // LEFT JOIN
query =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.CloudServer>() on new { a.CloudServerId, CloudServerCode = "" } equals new { b.CloudServerId, b.CloudServerCode } into u_b
from b in u_b.DefaultIfEmpty()
select a;
query = query.Where(a => a.CloudServer.CloudServerName != null);
result = query.ToList();

13. 右联查询

左关联和右关联的语法我这里用的是一样的,不过是 DefaultIfEmpty 方法加多了一个重载,DefaultIfEmpty(true) 即表示右关联。

 // RIGHT JOIN
query =
from a in context.GetTable<Model.CloudServer>()
join b in context.GetTable<Model.Client>() on a.CloudServerId equals b.CloudServerId into u_b
from b in u_b.DefaultIfEmpty(true)
where a.CloudServerName == null
select b;
result = query.ToList();

14. Union查询

我们的Union查询支持 UNION 操作后再分页哦~

 // UNION 注意UNION分页的写法,仅支持写在最后
var q1 = context.GetTable<Model.Client>().Where(x => x.ClientId == );
var q2 = context.GetTable<Model.Client>().Where(x => x.ClientId == );
var q3 = context.GetTable<Model.Client>().Where(x => x.ClientId == );
var query6 = q1.Union(q2).Union(q3);
var result6 = query6.ToList();
result6 = query6.Take().ToList();
result6 = query6.OrderBy(a => a.ClientId).Skip().ToList();
query6 = query6.Take();
result6 = query6.ToList();
query6 = query6.OrderBy(a => a.ClientId).Skip().Take();
result6 = query6.ToList();

15. 导航属性

 // 更简单的赋值方式
// 适用场景:在显示列表时只想显示外键表的一两个字段
query =
from a in context.GetTable<Model.Client>()
select new Model.Client(a)
{
CloudServer = a.CloudServer,
LocalServer = new Model.CloudServer
{
CloudServerId = a.CloudServerId,
CloudServerName = a.LocalServer.CloudServerName
}
};
result = query.ToList();

16. 一对一一对多导航

 // 1:1关系,1:n关系
query =
from a in context.GetTable<Model.Client>()
where a.ClientId >
orderby a.ClientId
select new Model.Client(a)
{
CloudServer = a.CloudServer,
Accounts = a.Accounts
};
result = query.ToList();

17. Include 语法

EntityFramework 有Include语法,咱也有,而且是实打实的一次性加载!!!

 // Include 语法
query =
context
.GetTable<Model.Client>()
.Include(a => a.CloudServer);
--query =
-- from a in query
-- join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
-- orderby a.ClientId
-- select new Model.Client(a)
-- {
-- CloudServer = a.CloudServer
-- };
result = query.ToList(); // 还是Include,无限主从孙 ###
query =
from a in context
.GetTable<Model.Client>()
.Include(a => a.Accounts)
.Include(a => a.Accounts[].Markets)
.Include(a => a.Accounts[].Markets[].Client)
where a.ClientId >
orderby a.ClientId
select a;
result = query.ToList(); // Include 分页
query =
from a in context
.GetTable<Model.Client>()
.Include(a => a.Accounts)
.Include(a => a.Accounts[].Markets)
.Include(a => a.Accounts[].Markets[].Client)
where a.ClientId >
orderby a.ClientId
select a;
query = query
.Where(a => a.ClientId > && a.CloudServer.CloudServerId > )
.Skip()
.Take();
result = query.ToList();
query =
from a in context
.GetTable<Model.Client>()
.Include(a => a.CloudServer)
.Include(a => a.Accounts)
where a.ClientId >
select a;
query = query.OrderBy(a => a.ClientId);
result = query.ToList(); // Include 语法查询 主 从 孙 关系<注:相同的导航属性不能同时用include和join>
var query1 =
from a in
context
.GetTable<Model.Client>()
.Include(a => a.CloudServer)
.Include(a => a.Accounts)
.Include(a => a.Accounts[].Markets)
.Include(a => a.Accounts[].Markets[].Client)
group a by new { a.ClientId, a.ClientCode, a.ClientName, a.CloudServer.CloudServerId } into g
select new Model.Client
{
ClientId = g.Key.ClientId,
ClientCode = g.Key.ClientCode,
ClientName = g.Key.ClientName,
CloudServerId = g.Key.CloudServerId,
Qty = g.Sum(a => a.Qty)
};
query1 = query1
.Where(a => a.ClientId > )
.OrderBy(a => a.ClientId)
.Skip()
.Take()
;
var result1 = query1.ToList();

18. 分组查询

 var query2 =
from a in context.GetTable<Model.Client>()
group a by a.ClientId into g
select new
{
ClientId = g.Key,
Qty = g.Sum(a => a.Qty)
};
query2 = query2.OrderBy(a => a.ClientId).ThenBy(a => a.Qty);

19. 聚合函数

 var result1 = query2.Max(a => a.ClientId);
var result2 = query2.Sum(a => a.Qty);
var result3 = query2.Min(a => a.ClientId);
var result4= query2.Average(a => a.Qty);
var result5 = query2.Count();

20. 分组分页

 // 分组后再分页
var query8 =
from a in context.GetTable<Model.Client>()
where a.ClientName == "TAN"
group a by new { a.ClientId, a.ClientName } into g
where g.Key.ClientId >
orderby new { g.Key.ClientName, g.Key.ClientId }
select new
{
Id = g.Key.ClientId,
Name = g.Min(a => a.ClientId)
};
query8 = query8.Skip().Take();
var result8 = query8.ToList();

21. 子查询

 // 强制转为子查询
query =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId into u_c
from b in u_c.DefaultIfEmpty()
select a;
query = query.OrderBy(a => a.ClientId).Skip().Take().AsSubQuery();
query = from a in query
join b in context.GetTable<Model.Client>() on a.ClientId equals b.ClientId
select a;
result = query.ToList();

22. Any 查询

 // Any
var isAny = context.GetTable<Model.Client>().Any();
isAny = context.GetTable<Model.Client>().Any(a => a.ActiveDate == DateTime.Now);
isAny = context.GetTable<Model.Client>().Distinct().Any(a => a.ActiveDate == DateTime.Now);
isAny = context.GetTable<Model.Client>().OrderBy(a => a.ClientId).Skip().Take().Any(a => a.ActiveDate == DateTime.Now);
//SQL=>
//IF EXISTS(
// SELECT TOP 1 1
// FROM[Bas_Client] t0
// WHERE t0.[ActiveDate] = '2018-08-15 14:07:09.784'
//) SELECT 1 ELSE SELECT 0

23. 单个删除

 // 1. 删除单个记录
var demo = new TDemo { DemoId = };
context.Delete(demo);
context.SubmitChanges();

24. 批量删除

 // 2.WHERE 条件批量删除
context.Delete<TDemo>(a => a.DemoId == || a.DemoId == || a.DemoName == "N0000004");
var qeury =
context
.GetTable<TDemo>()
.Where(a => a.DemoId == || a.DemoId == || a.DemoName == "N0000004");
// 2.WHERE 条件批量删除
context.Delete<TDemo>(qeury);
context.SubmitChanges();

25. 多表关联删除

 // 3.Query 关联批量删除
var query1 =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.ClientAccount>() on a.ClientId equals b.ClientId
join c in context.GetTable<Model.ClientAccountMarket>() on new { b.ClientId, b.AccountId } equals new { c.ClientId, c.AccountId }
where c.ClientId == && c.AccountId == "" && c.MarketId ==
select a;
context.Delete<Model.Client>(query1); // oracle 不支持导航属性关联删除
// 3.Query 关联批量删除
var query2 =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.ClientAccount>() on a.ClientId equals b.ClientId
where a.CloudServer.CloudServerId == && a.LocalServer.CloudServerId ==
select a;
context.Delete<Model.Client>(query2);
// 4.Query 关联批量删除
var query3 =
from a in context.GetTable<Model.Client>()
where a.CloudServer.CloudServerId == && a.LocalServer.CloudServerId ==
select a;
context.Delete<Model.Client>(query3); // 5.子查询批量删除
// 子查询更新
var sum =
from a in context.GetTable<Model.ClientAccount>()
where a.ClientId <=
group a by new { a.ClientId } into g
select new Model.Client
{
ClientId = g.Key.ClientId,
Qty = g.Sum(a => a.Qty)
};
var query4 =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
join c in context.GetTable<Model.CloudServer>() on a.CloudServerId equals c.CloudServerId
join d in sum on a.ClientId equals d.ClientId
where a.ClientId > && a.CloudServerId <
select a;
context.Delete<Model.Client>(query4);

26. 单个更新

 var demo = context
.GetTable<TDemo>()
.FirstOrDefault(x => x.DemoId > ); // 整个实体更新
demo.DemoName = "001'.N";
context.Update(demo);
context.SubmitChanges();

27.批量更新

 // 2.WHERE 条件批量更新
context.Update<TDemo>(x => new TDemo
{
DemoDateTime2 = DateTime.UtcNow,
DemoDateTime2_Nullable = null,
//DemoTime_Nullable = ts
}, x => x.DemoName == "001'.N" || x.DemoCode == "001'.N");
context.SubmitChanges();

28. 多表关联更新

这里还支持将B表字段的值更新回A表,有多方便你自己体会。事先声明,Oracle和Postgre是不支持这种sao操作的。

 // 3.Query 关联批量更新
var query =
from a in context.GetTable<Model.Client>()
where a.CloudServer.CloudServerId !=
select a;
context.Update<Model.Client>(a => new Model.Client
{
Remark = "001.TAN"
}, query); // 更新本表值等于从表的字段值
query =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
join c in context.GetTable<Model.ClientAccount>() on a.ClientId equals c.ClientId
where c.AccountId == ""
select a;
context.Update<Model.Client, Model.CloudServer>((a, b) => new Model.Client
{
CloudServerId = b.CloudServerId,
Remark = "001.TAN"
}, query);
context.SubmitChanges();

29. 子查询更新

  // 子查询更新
var sum =
from a in context.GetTable<Model.ClientAccount>()
where a.ClientId >
group a by new { a.ClientId } into g
select new Model.Client
{
ClientId = g.Key.ClientId,
Qty = g.Sum(a => a.Qty)
};
if (_databaseType == DatabaseType.SqlServer || _databaseType == DatabaseType.MySql)
{
var uQuery =
from a in context.GetTable<Model.Client>()
join b in sum on a.ClientId equals b.ClientId
where a.ClientId > && b.ClientId >
select a;
context.Update<Model.Client, Model.Client>((a, b) => new Model.Client { Qty = b.Qty }, uQuery);
}
else
{
// npg oracle 翻译成 EXISTS,更新字段的值不支持来自子查询
var uQuery =
from a in context.GetTable<Model.Client>()
join b in sum on a.ClientId equals b.ClientId
where a.ClientId > // b.ClientId > 0
select a;
context.Update<Model.Client>(a => new Model.Client { Qty = }, uQuery);
}
context.SubmitChanges();

30. 带自增列新增

 // 带自增列
var demo = new TDemo
{
DemoCode = "D0000001",
DemoName = "N0000001",
DemoBoolean = true,
DemoChar = 'A',
DemoNChar = 'B',
DemoByte = ,
DemoDate = DateTime.Now,
DemoDateTime = DateTime.Now,
DemoDateTime2 = DateTime.Now,
DemoDecimal = ,
DemoDouble = ,
DemoFloat = ,
DemoGuid = Guid.NewGuid(),
DemoShort = ,
DemoInt = ,
DemoLong =
};
context.Insert(demo);
context.SubmitChanges(); var demo2 = new TDemo
{
DemoCode = "D0000002",
DemoName = "N0000002",
DemoBoolean = true,
DemoChar = 'A',
DemoNChar = 'B',
DemoByte = ,
DemoDate = DateTime.Now,
DemoDateTime = DateTime.Now,
DemoDateTime2 = DateTime.Now,
DemoDecimal = ,
DemoDouble = ,
DemoFloat = ,
DemoGuid = Guid.NewGuid(),
DemoShort = ,
DemoInt = ,
DemoLong =
};
context.Insert(demo2); var demo3 = new TDemo
{
DemoCode = "D0000003",
DemoName = "N0000003",
DemoBoolean = true,
DemoChar = 'A',
DemoNChar = 'B',
DemoByte = ,
DemoDate = DateTime.Now,
DemoDateTime = DateTime.Now,
DemoDateTime2 = DateTime.Now,
DemoDecimal = ,
DemoDouble = ,
DemoFloat = ,
DemoGuid = Guid.NewGuid(),
DemoShort = ,
DemoInt = ,
DemoLong =
};
context.Insert(demo3);
context.Insert(demo);
context.SubmitChanges();

31. 批量新增

批量新增翻译的SQL不带参数,只是纯SQL文本。SQLSERVER的同学如果想更快,可以尝尝 SqlDbContext.BulkCopy方法。

  // 批量增加
// 产生 INSERT INTO VALUES(),(),()... 语法。注意这种批量增加的方法并不能给自增列自动赋值
context.Delete<TDemo>(x => x.DemoId > );
demos = new List<TDemo>();
for (int i = ; i < ; i++)
{
TDemo d = new TDemo
{
DemoCode = "D0000001",
DemoName = "N0000001",
DemoBoolean = true,
DemoChar = 'A',
DemoNChar = 'B',
DemoByte = ,
DemoDate = DateTime.Now,
DemoDateTime = DateTime.Now,
DemoDateTime2 = DateTime.Now,
DemoDecimal = ,
DemoDouble = ,
DemoFloat = ,
DemoGuid = Guid.NewGuid(),
DemoShort = ,
DemoInt = ,
DemoLong =
};
demos.Add(d);
}
context.Insert<TDemo>(demos);
context.SubmitChanges();

32. 关联查询新增

  // 子查询增
var sum =
from a in context.GetTable<Model.ClientAccount>()
where a.ClientId >
group a by new { a.ClientId } into g
select new Model.Client
{
ClientId = g.Key.ClientId,
Qty = g.Sum(a => a.Qty)
};
sum = sum.AsSubQuery(); maxId = context.GetTable<Model.Client>().Max(x => x.ClientId);
nextId = maxId + ;
var nQuery =
from a in sum
join b in context.GetTable<Model.Client>() on a.ClientId equals b.ClientId into u_b
from b in u_b.DefaultIfEmpty()
where b.ClientId == null
select new Model.Client
{
ClientId = SqlMethod.RowNumber<int>(x => a.ClientId) + nextId,
ClientCode = "ABC3",
ClientName = "啊啵呲3",
CloudServerId = ,
State = ,
Qty = a.Qty,
};
context.Insert(nQuery);

33. 增删改同时查出数据

 context.Update<Model.Client>(x => new Model.Client
{
ClientName = "蒙3"
}, x => x.ClientId == );
var query =
from a in context.GetTable<Model.Client>()
where a.ClientId ==
select ;
context.AddQuery(query);
List<int> result1 = null;
context.SubmitChanges(out result1); context.Update<Model.Client>(x => new Model.Client
{
ClientName = "蒙4"
}, x => x.ClientId == );
query =
from a in context.GetTable<Model.Client>()
where a.ClientId ==
select ;
context.AddQuery(query);
var query2 =
from a in context.GetTable<Model.Client>()
where a.ClientId ==
select ;
context.AddQuery(query2);
result1 = null;
List<int> result2 = null;
context.SubmitChanges(out result1, out result2);

34. 一次性加载多个列表

 // 一性加载多个列表 ****
var query3 =
from a in context.GetTable<Model.Client>()
where a.ClientId >= && a.ClientId <=
select ;
var query4 =
from a in context.GetTable<Model.Client>()
where a.ClientId >= && a.ClientId <=
select ;
var tuple = context.Database.ExecuteMultiple<int, int>(query3, query4); query3 =
from a in context.GetTable<Model.Client>()
where a.ClientId >= && a.ClientId <=
select ;
query4 =
from a in context.GetTable<Model.Client>()
where a.ClientId >= && a.ClientId <=
select ;
var query5 =
from a in context.GetTable<Model.Client>()
where a.ClientId >= && a.ClientId <=
select ;
var tuple2 = context.Database.ExecuteMultiple<int, int, int>(query3, query4, query5);

35. 事务操作

借鉴 EntityFramework的思想,本框架也支持自身开启事务,或者从其它上下文开启事务后再在本框架使用该事务。

// 事务1. 上下文独立事务
try
{
using (var transaction = context.Database.BeginTransaction())
{
var result = context.GetTable<Model.Client>().FirstOrDefault(x => x.ClientId <= );
context.Update<Model.Client>(x => new Model.Client
{
ClientName = "事务1"
}, x => x.ClientId == result.ClientId);
context.SubmitChanges();
result = context.GetTable<Model.Client>().FirstOrDefault(x => x.ClientId == result.ClientId); context.Update<Model.Client>(x => new Model.Client
{
ClientName = "事务2"
}, x => x.ClientId == result.ClientId);
context.SubmitChanges();
result = context.GetTable<Model.Client>().FirstOrDefault(x => x.ClientId == result.ClientId); //throw new Exception("假装异常");
//transaction.Rollback();
transaction.Commit();
}
}
finally
{
// 开启事务后必需显式释放资源
context.Dispose();
} // 事务2. 使用其它的事务
IDbTransaction transaction2 = null;
IDbConnection connection = null;
try
{
connection = context.Database.DbProviderFactory.CreateConnection();
connection.ConnectionString = context.Database.ConnectionString;
if (connection.State != ConnectionState.Open) connection.Open();
transaction2 = connection.BeginTransaction(); // 指定事务
context.Database.Transaction = transaction2; var result = context.GetTable<Model.Client>().FirstOrDefault(x => x.ClientId <= );
context.Update<Model.Client>(x => new Model.Client
{
ClientName = "事务3"
}, x => x.ClientId == result.ClientId);
context.SubmitChanges();
result = context.GetTable<Model.Client>().FirstOrDefault(x => x.ClientId == result.ClientId); context.Update<Model.Client>(x => new Model.Client
{
ClientName = "事务4"
}, x => x.ClientId == result.ClientId);
result = context.GetTable<Model.Client>().FirstOrDefault(x => x.ClientId == result.ClientId); string sql = @"UPDATE Bas_Client SET ClientName = N'事务5' WHERE ClientID=2;UPDATE Bas_Client SET ClientName = N'事务6' WHERE ClientID=3;";
context.AddQuery(sql);
context.SubmitChanges(); transaction2.Commit();
}
catch
{
if (transaction2 != null) transaction2.Rollback();
throw;
}
finally
{
if (transaction2 != null) transaction2.Dispose();
if (connection != null) connection.Close();
if (connection != null) connection.Dispose(); context.Dispose();
}

36. 表变量

SQLSERVER的童鞋看过来,你要的爽本框架都能给~

 // 声明表变量
var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo<SqlServerModel.JoinKey>();
context.AddQuery(string.Format("DECLARE {0} [{1}]", typeRuntime.TableName, typeRuntime.TableName.TrimStart('@')));
List<SqlServerModel.JoinKey> keys = new List<SqlServerModel.JoinKey>
{
new SqlServerModel.JoinKey{ Key1 = },
new SqlServerModel.JoinKey{ Key1 = },
};
// 向表变量写入数据
context.Insert<SqlServerModel.JoinKey>(keys);
// 像物理表一样操作表变量
var query =
from a in context.GetTable<Model.Client>()
join b in context.GetTable<SqlServerModel.JoinKey>() on a.ClientId equals b.Key1
select a;
context.AddQuery(query);
// 提交查询结果
List<Model.Client> result = null;
context.SubmitChanges(out result);

【结语】

  XFramework 已成熟运用于我们公司的多个核心项目,完全代替了之前的 Dapper + DbHelper的数据持久方案。从最初只支持SQLSERVER到支持MySQL、Postgre和Oracle,一个多月的熬夜坚持,个中酸爽只有经历过才能体会。你的喜爱和支持是我在开源的路上一路狂奔的最大动力,撸码不易,不喜请轻喷。但我相信,这绝对是一款人性化、有温度的数据持久框架!!!
  XFramework 现已完全开源,遵循 Apache2.0 协议,托管地址:
  码云:https://gitee.com/TANZAME/TZM.XFramework
  GitHub:https://github.com/TANZAME/TZM.XFramework

  ORM 技术交流群:816425449

  

【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework的更多相关文章

  1. 【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework 之优雅增删改

    [前言] 大家好,我是TANZAME.出乎意料的,我们在立冬的前一天又见面了,天气慢慢转凉,朋友们注意添衣保暖,愉快撸码.距离 TZM.XFramework 的首秀已数月有余,期间收到不少朋友的鼓励. ...

  2. 【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework 之让代码更优雅

    [前言] 大家好,我是TANZAME.出乎意料的,我们在立冬的前一天又见面了,天气慢慢转凉,朋友们注意添衣保暖,愉快撸码.距离 TZM.XFramework 的首秀已数月有余,期间收到不少朋友的鼓励. ...

  3. 轻量级高性能ORM框架:Dapper高级玩法

    Dapper高级玩法1: 数据库中带下划线的表字段自动匹配无下划线的Model字段. Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; 备 ...

  4. PetaPoco - 轻量级高性能的ORM框架(支持.NET Core)

    我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db. 而且市面上的orm框架有很多,有重量级的Entity Framework,有 ...

  5. 轻量级.NET ORM、高性能.NET ORM 之 SqlSugar 开源ORM - ASP.NET

    3.0最新API: http://www.cnblogs.com/sunkaixuan/p/5911334.html 1.前言/Preface SqlSugar从去年到现在已经一年了,版本从1.0升到 ...

  6. 分享自己写的基于Dapper的轻量级ORM框架~

    1.说明 本项目是一个使用.NET Standard 2.0开发的,基于 Dapper 的轻量级 ORM 框架,包含基本的CRUD以及根据表达式进行一些操作的方法,目前只针对单表,不包含多表连接操作. ...

  7. Android高性能ORM数据库DBFlow入门

    DBFlow,综合了 ActiveAndroid, Schematic, Ollie,Sprinkles 等库的优点.同时不是基于反射,所以性能也是非常高,效率紧跟greenDAO其后.基于注解,使用 ...

  8. 基于nginx+lua+redis高性能api应用实践

    基于nginx+lua+redis高性能api应用实践 前言 比较传统的服务端程序(PHP.FAST CGI等),大多都是通过每产生一个请求,都会有一个进程与之相对应,请求处理完毕后相关进程自动释放. ...

  9. FluentData - 轻量级.NET ORM持久化技术解决方式

    FluentData - 轻量级.NET ORM持久化技术解决方式   文件夹:    一.什么是ORM?  二.使用ORM的优势  三.使用ORM的缺点  四.NET下的ORM框架有哪些?  五.几 ...

随机推荐

  1. linux系统——hosts文件修改

    1. 关于/etc/host,主机名和IP配置文件 Hosts - The static table lookup for host name(主机名查询静态表) Linux 的/etc/hosts是 ...

  2. Python 读取 pkl文件

    使用python 的cPickle 库中的load函数,可以读取pkl文件的内容 import cPickle as pickle fr = open('mnist.pkl') #open的参数是pk ...

  3. git常用命令符

    全局配置 $ git config --global user.name "姓名" 告诉git你是谁 $ git config --global user.email " ...

  4. pat 团体天梯赛 L1-039. 古风排版

    L1-039. 古风排版 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 中国的古人写文字,是从右向左竖向排版的.本题就请你编写 ...

  5. kernel thread vs user thread

    The most important difference is they use different memory, the kernel mode thread can access any ke ...

  6. AC日记——数据流中的算法 51nod 1785

    数据流中的算法 思路: 线段树模拟: 时间刚刚卡在边界上,有时超时一个点,有时能过: 来,上代码: #include <cstdio> #include <cstring> # ...

  7. Codeforces Gym100971 B.Derangement (IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13)

    昨天训练打的Gym,今天写题解. 这个题就是输出的时候有点小问题,其他的都很简单. 代码: #include<iostream> #include<cstring> #incl ...

  8. C# ASP.NET中Process.Start没有反应也没有报错的解决方法

    最近有一个很坑的需求,在ASP.NET中打开一个access,还要用process.start打开,调试时一切正常,到了发布后就没有反应,找了一下午,各种设文件夹权限也不行,最后把应用程序池改成管理员 ...

  9. Java 大数(整数+浮点数) 基本函数

    import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; public class Main { pu ...

  10. codevs——2853 方格游戏(棋盘DP)

    时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解  题目描述 Description 菜菜看到了一个游戏,叫做方格游戏~ 游戏规则是这样的: 在一个n*n的 ...