zoukankan      html  css  js  c++  java
  • 【原创】基于.NET的轻量级高性能 ORM

     【前言】

      接上一篇《【原创】打造基于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)]

     1         [Table(Name = "Bas_Client")]
     2         public partial class Client
     3         {
     4             /// <summary>
     5             /// 初始化 <see cref="Client"/> 类的新实例
     6             /// </summary>
     7             public Client()
     8             {
     9                 this.CloudServerId = 0;
    10                 this.Qty = 0;
    11                 this.HookConstructor();
    12             }
    13 
    14             /// <summary>
    15             /// 初始化 <see cref="Client"/> 类的新实例
    16             /// </summary>
    17             public Client(Client model)
    18             {
    19                 this.CloudServerId = 0;
    20                 this.Qty = 0;
    21                 this.HookConstructor();
    22             }
    23 
    24             /// <summary>
    25             /// clientid
    26             /// </summary>
    27             [Column(IsKey = true)]
    28             public virtual int ClientId { get; set; }
    29 
    30             /// <summary>
    31             /// clientcode
    32             /// </summary>
    33             public virtual string ClientCode { get; set; }
    34 
    35             /// <summary>
    36             /// clientname
    37             /// </summary>
    38             public virtual string ClientName { get; set; }
    39 
    40             /// <summary>
    41             /// cloudserverid
    42             /// </summary>
    43             [Column(Default = 0)]
    44             public virtual int CloudServerId { get; set; }
    45 
    46             /// <summary>
    47             /// activedate
    48             /// </summary>
    49             public virtual Nullable<DateTime> ActiveDate { get; set; }
    50 
    51             /// <summary>
    52             /// qty
    53             /// </summary>
    54             [Column(Default = 0)]
    55             public virtual int Qty { get; set; }
    56 
    57             /// <summary>
    58             /// state
    59             /// </summary>
    60             public virtual byte State { get; set; }
    61 
    62             /// <summary>
    63             /// remark
    64             /// </summary>
    65             [Column(Default = "'默认值'")]
    66             public virtual string Remark { get; set; }
    67 
    68             [ForeignKey("CloudServerId")]
    69             public virtual CloudServer CloudServer { get; set; }
    70 
    71             [ForeignKey("CloudServerId")]
    72             public virtual CloudServer LocalServer { get; set; }
    73 
    74             [ForeignKey("ClientId")]
    75             public virtual List<ClientAccount> Accounts { get; set; }
    76 
    77             /// <summary>
    78             /// 构造函数勾子
    79             /// </summary>
    80             partial void HookConstructor();
    81         }
    View Code

    2. 上下文定义   

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

    3. 匿名类型

     1 //// 匿名类
     2 var guid = Guid.NewGuid();
     3 var dynamicQuery =
     4     from a in context.GetTable<TDemo>()
     5     where a.DemoId <= 10
     6     select new
     7     {
     8         DemoId = 12,
     9         DemoCode = a.DemoCode,
    10         DemoName = a.DemoName,
    11         DemoDateTime_Nullable = a.DemoDateTime_Nullable,
    12         DemoDate = sDate,
    13         DemoDateTime = sDate,
    14         DemoDateTime2 = sDate_null,
    15         DemoGuid = guid,
    16         DemoEnum = Model.State.Complete,        // 枚举类型支持
    17         DemoEnum2 = Model.State.Executing,
    18     };
    19 var result0 = dynamicQuery.ToList();
    20 
    21 // 点标记
    22 dynamicQuery = context
    23     .GetTable<TDemo>()
    24     .Where(a => a.DemoId <= 10)
    25     .Select(a => new
    26     {
    27         DemoId = 13,
    28         DemoCode = a.DemoCode,
    29         DemoName = a.DemoName,
    30         DemoDateTime_Nullable = a.DemoDateTime_Nullable,
    31         DemoDate = sDate,
    32         DemoDateTime = sDate,
    33         DemoDateTime2 = sDate_null,
    34         DemoGuid = Guid.NewGuid(),
    35         DemoEnum = Model.State.Complete,
    36         DemoEnum2 = Model.State.Executing
    37     });
    38 result0 = dynamicQuery.ToList();
    View Code

     4. 所有字段

     1  // Date,DateTime,DateTime2 支持
     2 var query =
     3     from a in context.GetTable<TDemo>()
     4     where a.DemoId <= 10 && a.DemoDate > sDate && a.DemoDateTime >= sDate && a.DemoDateTime2 > sDate
     5     select a;
     6 var result1 = query.ToList();
     7 // 点标记
     8 query = context
     9     .GetTable<TDemo>()
    10     .Where(a => a.DemoId <= 10 && a.DemoDate > sDate && a.DemoDateTime >= sDate && a.DemoDateTime2 > sDate);
    11 result1 = query.ToList();
    View Code

    5. 指定字段

     1 // 指定字段
     2 query = from a in context.GetTable<TDemo>()
     3         where a.DemoId <= 10
     4         select new TDemo
     5         {
     6             DemoId = (int)a.DemoId,
     7             DemoCode = (a.DemoCode ?? "N001"),
     8             DemoName = a.DemoId.ToString(),
     9             DemoDateTime_Nullable = a.DemoDateTime_Nullable,
    10             DemoDate = sDate,
    11             DemoDateTime = sDate,
    12             DemoDateTime2 = sDate
    13         };
    14 result1 = query.ToList();
    15 // 点标记
    16 query = context
    17     .GetTable<TDemo>()
    18     .Where(a => a.DemoCode != a.DemoId.ToString() && a.DemoName != a.DemoId.ToString() && a.DemoChar == 'A' && a.DemoNChar == 'B')
    19     .Select(a => new TDemo
    20     {
    21         DemoId = a.DemoId,
    22         DemoCode = a.DemoName == "张三" ? "李四" : "王五",
    23         DemoName = a.DemoCode == "张三" ? "李四" : "王五",
    24         DemoChar = 'A',
    25         DemoNChar = 'B',
    26         DemoDateTime_Nullable = a.DemoDateTime_Nullable,
    27         DemoDate = sDate,
    28         DemoDateTime = sDate,
    29         DemoDateTime2 = sDate
    30     });
    31 result1 = query.ToList();
    View Code

     6.构造函数

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

     1 // 构造函数
     2 var query =
     3         from a in context.GetTable<Model.Demo>()
     4         where a.DemoId <= 10
     5         select new Model.Demo(a);
     6 var r1 = query.ToList();
     7 //SQL=> 
     8 //SELECT 
     9 //t0.[DemoId] AS [DemoId],
    10 //t0.[DemoCode] AS [DemoCode],
    11 //t0.[DemoName] AS [DemoName],
    12 //...
    13 //FROM [Sys_Demo] t0 
    14 //WHERE t0.[DemoId] <= 10
    15 query =
    16     from a in context.GetTable<Model.Demo>()
    17     where a.DemoId <= 10
    18     select new Model.Demo(a.DemoId, a.DemoName);
    19 r1 = query.ToList();
    View Code

     7. 分页查询

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

    8. 过滤条件

     1 // 过滤条件
     2 query = from a in context.GetTable<TDemo>()
     3         where a.DemoName == "D0000002" || a.DemoCode == "D0000002"
     4         select a;
     5 result1 = query.ToList();
     6 // 点标记
     7 query = context.GetTable<TDemo>().Where(a => a.DemoName == "D0000002" || a.DemoCode == "D0000002");
     8 result1 = query.ToList();
     9 query = context.GetTable<TDemo>().Where(a => a.DemoName.Contains("004"));
    10 result1 = query.ToList();
    11 query = context.GetTable<TDemo>().Where(a => a.DemoCode.StartsWith("Code000036"));
    12 result1 = query.ToList();
    13 query = context.GetTable<TDemo>().Where(a => a.DemoCode.EndsWith("004"));
    14 result1 = query.ToList();
    View Code

    9. 更多条件

     1 // 支持的查询条件
     2 // 区分 nvarchar,varchar,date,datetime,datetime2 字段类型
     3 // 支持的字符串操作=> Trim | TrimStart | TrimEnd | ToString | Length
     4 int m_byte = 9;
     5 Model.State state = Model.State.Complete;
     6 query = from a in context.GetTable<TDemo>()
     7         where
     8             a.DemoCode == "002" &&
     9             a.DemoName == "002" &&
    10             a.DemoCode.Contains("TAN") &&                                   // LIKE '%%'
    11             a.DemoName.Contains("TAN") &&                                   // LIKE '%%'
    12             a.DemoCode.StartsWith("TAN") &&                                 // LIKE 'K%'
    13             a.DemoCode.EndsWith("TAN") &&                                   // LIKE '%K'
    14             a.DemoCode.Length == 12 &&                                      // LENGTH
    15             a.DemoCode.TrimStart() == "TF" &&
    16             a.DemoCode.TrimEnd() == "TF" &&
    17             a.DemoCode.TrimEnd() == "TF" &&
    18             a.DemoCode.Substring(0) == "TF" &&
    19             a.DemoDate == DateTime.Now &&
    20             a.DemoDateTime == DateTime.Now &&
    21             a.DemoDateTime2 == DateTime.Now &&
    22             a.DemoName == (
    23                 a.DemoDateTime_Nullable == null ? "NULL" : "NOT NULL") &&   // 三元表达式
    24             a.DemoName == (a.DemoName ?? a.DemoCode) &&                     // 二元表达式
    25             new[] { 1, 2, 3 }.Contains(a.DemoId) &&                         // IN(1,2,3)
    26             new List<int> { 1, 2, 3 }.Contains(a.DemoId) &&                 // IN(1,2,3)
    27             new List<int>(_demoIdList).Contains(a.DemoId) &&                // IN(1,2,3)
    28             a.DemoId == new List<int> { 1, 2, 3 }[0] &&                     // IN(1,2,3)
    29             _demoIdList.Contains(a.DemoId) &&                          // IN(1,2,3)
    30             a.DemoName == _demoName &&
    31             a.DemoCode == (a.DemoCode ?? "CODE") &&
    32             new List<string> { "A", "B", "C" }.Contains(a.DemoCode) &&
    33             a.DemoByte == (byte)m_byte &&
    34             a.DemoByte == (byte)Model.State.Complete ||
    35             a.DemoInt == (int)Model.State.Complete ||
    36             a.DemoInt == (int)state ||
    37             (a.DemoName == "STATE" && a.DemoName == "REMARK")// OR 查询
    38         select a;
    39 result1 = query.ToList();
    View Code

    10. DataTable和DataSet

     1 // DataTable
     2 query = from a in context.GetTable<TDemo>()
     3         orderby a.DemoCode
     4         select a;
     5 query = query.Take(18);
     6 var result3 = context.Database.ExecuteDataTable(query);
     7 
     8 // DataSet
     9 var define = query.Resolve();
    10 List<DbCommandDefinition> sqlList = new List<DbCommandDefinition> { define, define, define };
    11 var result4 = context.Database.ExecuteDataSet(sqlList);
    View Code

    11. 内联查询

     1 // INNER JOIN
     2 var query =
     3     from a in context.GetTable<Model.Client>()
     4     join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
     5     where a.ClientId > 0
     6     select a;
     7 var result = query.ToList();
     8 // 点标记
     9 query = context
    10     .GetTable<Model.Client>()
    11     .Join(context.GetTable<Model.CloudServer>(), a => a.CloudServerId, b => b.CloudServerId, (a, b) => a)
    12     .Where(a => a.ClientId > 0);
    13 result = query.ToList();
    View Code

    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?

     1 // LEFT JOIN
     2 query =
     3         from a in context.GetTable<Model.Client>()
     4         join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId into u_b
     5         from b in u_b.DefaultIfEmpty()
     6         select a;
     7 query = query.Where(a => a.CloudServer.CloudServerName != null);
     8 result = query.ToList();
     9 
    10 // LEFT JOIN
    11 query =
    12         from a in context.GetTable<Model.Client>()
    13         join b in context.GetTable<Model.CloudServer>() on new { a.CloudServerId, CloudServerCode = "567" } equals new { b.CloudServerId, b.CloudServerCode } into u_b
    14         from b in u_b.DefaultIfEmpty()
    15         select a;
    16 query = query.Where(a => a.CloudServer.CloudServerName != null);
    17 result = query.ToList();
    View Code

     13. 右联查询

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

    1 // RIGHT JOIN
    2 query =
    3         from a in context.GetTable<Model.CloudServer>()
    4         join b in context.GetTable<Model.Client>() on a.CloudServerId equals b.CloudServerId into u_b
    5         from b in u_b.DefaultIfEmpty(true)
    6         where a.CloudServerName == null
    7         select b;
    8 result = query.ToList();
    View Code

     14. Union查询

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

     1 // UNION 注意UNION分页的写法,仅支持写在最后
     2 var q1 = context.GetTable<Model.Client>().Where(x => x.ClientId == 0);
     3 var q2 = context.GetTable<Model.Client>().Where(x => x.ClientId == 0);
     4 var q3 = context.GetTable<Model.Client>().Where(x => x.ClientId == 0);
     5 var query6 = q1.Union(q2).Union(q3);
     6 var result6 = query6.ToList();
     7 result6 = query6.Take(2).ToList();
     8 result6 = query6.OrderBy(a => a.ClientId).Skip(2).ToList();
     9 query6 = query6.Take(2);
    10 result6 = query6.ToList();
    11 query6 = query6.OrderBy(a => a.ClientId).Skip(1).Take(2);
    12 result6 = query6.ToList();
    View Code

    15. 导航属性

     1 // 更简单的赋值方式 
     2 // 适用场景:在显示列表时只想显示外键表的一两个字段
     3 query =
     4     from a in context.GetTable<Model.Client>()
     5     select new Model.Client(a)
     6     {
     7         CloudServer = a.CloudServer,
     8         LocalServer = new Model.CloudServer
     9         {
    10             CloudServerId = a.CloudServerId,
    11             CloudServerName = a.LocalServer.CloudServerName
    12         }
    13     };
    14 result = query.ToList();
    View Code

    16. 一对一一对多导航

     1 // 1:1关系,1:n关系
     2 query =
     3     from a in context.GetTable<Model.Client>()
     4     where a.ClientId > 0
     5     orderby a.ClientId
     6     select new Model.Client(a)
     7     {
     8         CloudServer = a.CloudServer,
     9         Accounts = a.Accounts
    10     };
    11 result = query.ToList();
    View Code

    17. Include 语法

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

     1 // Include 语法
     2 query =
     3     context
     4     .GetTable<Model.Client>()
     5     .Include(a => a.CloudServer);
     6 --query =
     7 --    from a in query
     8 --    join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
     9 --    orderby a.ClientId
    10 --    select new Model.Client(a)
    11 --    {
    12 --        CloudServer = a.CloudServer
    13 --    };
    14 result = query.ToList();
    15 
    16 // 还是Include,无限主从孙 ### 
    17 query =
    18     from a in context
    19         .GetTable<Model.Client>()
    20         .Include(a => a.Accounts)
    21         .Include(a => a.Accounts[0].Markets)
    22         .Include(a => a.Accounts[0].Markets[0].Client)
    23     where a.ClientId > 0
    24     orderby a.ClientId
    25     select a;
    26 result = query.ToList();
    27 
    28 // Include 分页
    29 query =
    30 from a in context
    31     .GetTable<Model.Client>()
    32     .Include(a => a.Accounts)
    33     .Include(a => a.Accounts[0].Markets)
    34     .Include(a => a.Accounts[0].Markets[0].Client)
    35 where a.ClientId > 0
    36 orderby a.ClientId
    37 select a;
    38 query = query
    39     .Where(a => a.ClientId > 0 && a.CloudServer.CloudServerId > 0)
    40     .Skip(10)
    41     .Take(20);
    42 result = query.ToList();
    43 query =
    44     from a in context
    45         .GetTable<Model.Client>()
    46         .Include(a => a.CloudServer)
    47         .Include(a => a.Accounts)
    48     where a.ClientId > 0
    49     select a;
    50 query = query.OrderBy(a => a.ClientId);
    51 result = query.ToList();
    52 
    53 // Include 语法查询 主 从 孙 关系<注:相同的导航属性不能同时用include和join>
    54 var query1 =
    55     from a in
    56         context
    57         .GetTable<Model.Client>()
    58         .Include(a => a.CloudServer)
    59         .Include(a => a.Accounts)
    60         .Include(a => a.Accounts[0].Markets)
    61         .Include(a => a.Accounts[0].Markets[0].Client)
    62     group a by new { a.ClientId, a.ClientCode, a.ClientName, a.CloudServer.CloudServerId } into g
    63     select new Model.Client
    64     {
    65         ClientId = g.Key.ClientId,
    66         ClientCode = g.Key.ClientCode,
    67         ClientName = g.Key.ClientName,
    68         CloudServerId = g.Key.CloudServerId,
    69         Qty = g.Sum(a => a.Qty)
    70     };
    71 query1 = query1
    72     .Where(a => a.ClientId > 0)
    73     .OrderBy(a => a.ClientId)
    74     .Skip(10)
    75     .Take(20)
    76     ;
    77 var result1 = query1.ToList();
    View Code

    18. 分组查询

    1 var query2 =
    2     from a in context.GetTable<Model.Client>()
    3     group a by a.ClientId into g
    4     select new
    5     {
    6         ClientId = g.Key,
    7         Qty = g.Sum(a => a.Qty)
    8     };
    9 query2 = query2.OrderBy(a => a.ClientId).ThenBy(a => a.Qty);
    View Code

    19. 聚合函数

    1 var result1 = query2.Max(a => a.ClientId);
    2 var result2 = query2.Sum(a => a.Qty);
    3 var result3 = query2.Min(a => a.ClientId);
    4 var result4= query2.Average(a => a.Qty);
    5 var result5 = query2.Count();
    View Code

    20. 分组分页

     1 // 分组后再分页
     2 var query8 =
     3         from a in context.GetTable<Model.Client>()
     4         where a.ClientName == "TAN"
     5         group a by new { a.ClientId, a.ClientName } into g
     6         where g.Key.ClientId > 0
     7         orderby new { g.Key.ClientName, g.Key.ClientId }
     8         select new
     9         {
    10             Id = g.Key.ClientId,
    11             Name = g.Min(a => a.ClientId)
    12         };
    13 query8 = query8.Skip(2).Take(3);
    14 var result8 = query8.ToList();
    View Code

    21. 子查询

     1 // 强制转为子查询
     2 query =
     3         from a in context.GetTable<Model.Client>()
     4         join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId into u_c
     5         from b in u_c.DefaultIfEmpty()
     6         select a;
     7 query = query.OrderBy(a => a.ClientId).Skip(10).Take(10).AsSubQuery();
     8 query = from a in query
     9         join b in context.GetTable<Model.Client>() on a.ClientId equals b.ClientId
    10         select a;
    11 result = query.ToList();
    View Code

    22. Any 查询

     1 // Any
     2 var isAny = context.GetTable<Model.Client>().Any();
     3 isAny = context.GetTable<Model.Client>().Any(a => a.ActiveDate == DateTime.Now);
     4 isAny = context.GetTable<Model.Client>().Distinct().Any(a => a.ActiveDate == DateTime.Now);
     5 isAny = context.GetTable<Model.Client>().OrderBy(a => a.ClientId).Skip(2).Take(5).Any(a => a.ActiveDate == DateTime.Now);
     6 //SQL=> 
     7 //IF EXISTS(
     8 //    SELECT TOP 1 1
     9 //    FROM[Bas_Client] t0
    10 //   WHERE t0.[ActiveDate] = '2018-08-15 14:07:09.784'
    11 //) SELECT 1 ELSE SELECT 0
    View Code

     23. 单个删除

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

    24. 批量删除

    1 // 2.WHERE 条件批量删除
    2 context.Delete<TDemo>(a => a.DemoId == 2 || a.DemoId == 3 || a.DemoName == "N0000004");
    3 var qeury =
    4     context
    5     .GetTable<TDemo>()
    6     .Where(a => a.DemoId == 2 || a.DemoId == 3 || a.DemoName == "N0000004");
    7 // 2.WHERE 条件批量删除
    8 context.Delete<TDemo>(qeury);
    9 context.SubmitChanges();
    View Code

    25. 多表关联删除

     1 // 3.Query 关联批量删除
     2 var query1 =
     3     from a in context.GetTable<Model.Client>()
     4     join b in context.GetTable<Model.ClientAccount>() on a.ClientId equals b.ClientId
     5     join c in context.GetTable<Model.ClientAccountMarket>() on new { b.ClientId, b.AccountId } equals new { c.ClientId, c.AccountId }
     6     where c.ClientId == 5 && c.AccountId == "1" && c.MarketId == 1
     7 select a;
     8 context.Delete<Model.Client>(query1);
     9 
    10 // oracle 不支持导航属性关联删除
    11 // 3.Query 关联批量删除
    12 var query2 =
    13     from a in context.GetTable<Model.Client>()
    14     join b in context.GetTable<Model.ClientAccount>() on a.ClientId equals b.ClientId
    15     where a.CloudServer.CloudServerId == 20 && a.LocalServer.CloudServerId == 2
    16     select a;
    17 context.Delete<Model.Client>(query2);
    18 // 4.Query 关联批量删除
    19 var query3 =
    20     from a in context.GetTable<Model.Client>()
    21     where a.CloudServer.CloudServerId == 20 && a.LocalServer.CloudServerId == 2
    22     select a;
    23 context.Delete<Model.Client>(query3);
    24 
    25 
    26  // 5.子查询批量删除
    27 // 子查询更新
    28 var sum =
    29     from a in context.GetTable<Model.ClientAccount>()
    30     where a.ClientId <= 20
    31     group a by new { a.ClientId } into g
    32     select new Model.Client
    33     {
    34         ClientId = g.Key.ClientId,
    35         Qty = g.Sum(a => a.Qty)
    36     };
    37 var query4 =
    38     from a in context.GetTable<Model.Client>()
    39     join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
    40     join c in context.GetTable<Model.CloudServer>() on a.CloudServerId equals c.CloudServerId
    41     join d in sum on a.ClientId equals d.ClientId
    42     where a.ClientId > 10 && a.CloudServerId < 0
    43     select a;
    44 context.Delete<Model.Client>(query4);
    View Code

    26. 单个更新

    1 var demo = context
    2     .GetTable<TDemo>()
    3     .FirstOrDefault(x => x.DemoId > 0);
    4 
    5 // 整个实体更新
    6 demo.DemoName = "001'.N";
    7 context.Update(demo);
    8 context.SubmitChanges();
    View Code

    27.批量更新

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

    28. 多表关联更新

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

     1 // 3.Query 关联批量更新
     2     var query =
     3     from a in context.GetTable<Model.Client>()
     4     where a.CloudServer.CloudServerId != 0
     5     select a;
     6 context.Update<Model.Client>(a => new Model.Client
     7 {
     8     Remark = "001.TAN"
     9 }, query);
    10 
    11 // 更新本表值等于从表的字段值
    12 query =
    13     from a in context.GetTable<Model.Client>()
    14     join b in context.GetTable<Model.CloudServer>() on a.CloudServerId equals b.CloudServerId
    15     join c in context.GetTable<Model.ClientAccount>() on a.ClientId equals c.ClientId
    16     where c.AccountId == "12"
    17     select a;
    18 context.Update<Model.Client, Model.CloudServer>((a, b) => new Model.Client
    19 {
    20     CloudServerId = b.CloudServerId,
    21     Remark = "001.TAN"
    22 }, query);
    23 context.SubmitChanges();
    View Code

    29. 子查询更新

     1  // 子查询更新
     2 var sum =
     3     from a in context.GetTable<Model.ClientAccount>()
     4     where a.ClientId > 0
     5     group a by new { a.ClientId } into g
     6     select new Model.Client
     7     {
     8         ClientId = g.Key.ClientId,
     9         Qty = g.Sum(a => a.Qty)
    10     };
    11 if (_databaseType == DatabaseType.SqlServer || _databaseType == DatabaseType.MySql)
    12 {
    13     var uQuery =
    14         from a in context.GetTable<Model.Client>()
    15         join b in sum on a.ClientId equals b.ClientId
    16         where a.ClientId > 0 && b.ClientId > 0
    17         select a;
    18     context.Update<Model.Client, Model.Client>((a, b) => new Model.Client { Qty = b.Qty }, uQuery);
    19 }
    20 else
    21 {
    22     // npg oracle 翻译成 EXISTS,更新字段的值不支持来自子查询
    23     var uQuery =
    24         from a in context.GetTable<Model.Client>()
    25         join b in sum on a.ClientId equals b.ClientId
    26         where a.ClientId > 0 // b.ClientId > 0
    27         select a;
    28     context.Update<Model.Client>(a => new Model.Client { Qty = 9 }, uQuery);
    29 }
    30 context.SubmitChanges();
    View Code

    30. 带自增列新增

     1 // 带自增列
     2 var demo = new TDemo
     3 {
     4     DemoCode = "D0000001",
     5     DemoName = "N0000001",
     6     DemoBoolean = true,
     7     DemoChar = 'A',
     8     DemoNChar = 'B',
     9     DemoByte = 64,
    10     DemoDate = DateTime.Now,
    11     DemoDateTime = DateTime.Now,
    12     DemoDateTime2 = DateTime.Now,
    13     DemoDecimal = 64,
    14     DemoDouble = 64,
    15     DemoFloat = 64,
    16     DemoGuid = Guid.NewGuid(),
    17     DemoShort = 64,
    18     DemoInt = 64,
    19     DemoLong = 64
    20 };
    21 context.Insert(demo);
    22 context.SubmitChanges();
    23 
    24 var demo2 = new TDemo
    25 {
    26     DemoCode = "D0000002",
    27     DemoName = "N0000002",
    28     DemoBoolean = true,
    29     DemoChar = 'A',
    30     DemoNChar = 'B',
    31     DemoByte = 65,
    32     DemoDate = DateTime.Now,
    33     DemoDateTime = DateTime.Now,
    34     DemoDateTime2 = DateTime.Now,
    35     DemoDecimal = 65,
    36     DemoDouble = 65,
    37     DemoFloat = 65,
    38     DemoGuid = Guid.NewGuid(),
    39     DemoShort = 65,
    40     DemoInt = 65,
    41     DemoLong = 65
    42 };
    43 context.Insert(demo2);
    44 
    45 var demo3 = new TDemo
    46 {
    47     DemoCode = "D0000003",
    48     DemoName = "N0000003",
    49     DemoBoolean = true,
    50     DemoChar = 'A',
    51     DemoNChar = 'B',
    52     DemoByte = 66,
    53     DemoDate = DateTime.Now,
    54     DemoDateTime = DateTime.Now,
    55     DemoDateTime2 = DateTime.Now,
    56     DemoDecimal = 66,
    57     DemoDouble = 66,
    58     DemoFloat = 66,
    59     DemoGuid = Guid.NewGuid(),
    60     DemoShort = 66,
    61     DemoInt = 66,
    62     DemoLong = 66
    63 };
    64 context.Insert(demo3);
    65 context.Insert(demo);
    66 context.SubmitChanges();
    View Code

    31. 批量新增

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

     1  // 批量增加
     2 // 产生 INSERT INTO VALUES(),(),()... 语法。注意这种批量增加的方法并不能给自增列自动赋值
     3 context.Delete<TDemo>(x => x.DemoId > 1000000);
     4 demos = new List<TDemo>();
     5 for (int i = 0; i < 1002; i++)
     6 {
     7     TDemo d = new TDemo
     8     {
     9         DemoCode = "D0000001",
    10         DemoName = "N0000001",
    11         DemoBoolean = true,
    12         DemoChar = 'A',
    13         DemoNChar = 'B',
    14         DemoByte = 64,
    15         DemoDate = DateTime.Now,
    16         DemoDateTime = DateTime.Now,
    17         DemoDateTime2 = DateTime.Now,
    18         DemoDecimal = 64,
    19         DemoDouble = 64,
    20         DemoFloat = 64,
    21         DemoGuid = Guid.NewGuid(),
    22         DemoShort = 64,
    23         DemoInt = 64,
    24         DemoLong = 64
    25     };
    26     demos.Add(d);
    27 }
    28 context.Insert<TDemo>(demos);
    29 context.SubmitChanges();
    View Code

    32. 关联查询新增

     1  // 子查询增
     2 var sum =
     3     from a in context.GetTable<Model.ClientAccount>()
     4     where a.ClientId > 0
     5     group a by new { a.ClientId } into g
     6     select new Model.Client
     7     {
     8         ClientId = g.Key.ClientId,
     9         Qty = g.Sum(a => a.Qty)
    10     };
    11 sum = sum.AsSubQuery();
    12 
    13 maxId = context.GetTable<Model.Client>().Max(x => x.ClientId);
    14 nextId = maxId + 1;
    15 var nQuery =
    16     from a in sum
    17     join b in context.GetTable<Model.Client>() on a.ClientId equals b.ClientId into u_b
    18     from b in u_b.DefaultIfEmpty()
    19     where b.ClientId == null
    20     select new Model.Client
    21     {
    22         ClientId = SqlMethod.RowNumber<int>(x => a.ClientId) + nextId,
    23         ClientCode = "ABC3",
    24         ClientName = "啊啵呲3",
    25         CloudServerId = 11,
    26         State = 3,
    27         Qty = a.Qty,
    28     };
    29 context.Insert(nQuery);
    View Code

    33. 增删改同时查出数据

     1 context.Update<Model.Client>(x => new Model.Client
     2 {
     3     ClientName = "蒙3"
     4 }, x => x.ClientId == 3);
     5 var query =
     6     from a in context.GetTable<Model.Client>()
     7     where a.ClientId == 1
     8     select 5;
     9 context.AddQuery(query);
    10 List<int> result1 = null;
    11 context.SubmitChanges(out result1);
    12 
    13 context.Update<Model.Client>(x => new Model.Client
    14 {
    15     ClientName = "蒙4"
    16 }, x => x.ClientId == 4);
    17 query =
    18     from a in context.GetTable<Model.Client>()
    19     where a.ClientId == 1
    20     select 5;
    21 context.AddQuery(query);
    22 var query2 =
    23     from a in context.GetTable<Model.Client>()
    24     where a.ClientId == 1
    25     select 6;
    26 context.AddQuery(query2);
    27 result1 = null;
    28 List<int> result2 = null;
    29 context.SubmitChanges(out result1, out result2);
    View Code

    34. 一次性加载多个列表

     1 // 一性加载多个列表 ****
     2 var query3 =
     3     from a in context.GetTable<Model.Client>()
     4     where a.ClientId >= 1 && a.ClientId <= 10
     5     select 5;
     6 var query4 =
     7     from a in context.GetTable<Model.Client>()
     8     where a.ClientId >= 1 && a.ClientId <= 10
     9     select 6;
    10 var tuple = context.Database.ExecuteMultiple<int, int>(query3, query4);
    11 
    12 query3 =
    13     from a in context.GetTable<Model.Client>()
    14     where a.ClientId >= 1 && a.ClientId <= 10
    15     select 5;
    16 query4 =
    17     from a in context.GetTable<Model.Client>()
    18     where a.ClientId >= 1 && a.ClientId <= 10
    19     select 6;
    20 var  query5 =
    21     from a in context.GetTable<Model.Client>()
    22     where a.ClientId >= 1 && a.ClientId <= 10
    23     select 7;
    24 var tuple2 = context.Database.ExecuteMultiple<int, int, int>(query3, query4, query5);
    View Code

    35. 事务操作

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

    // 事务1. 上下文独立事务
    try
    {
        using (var transaction = context.Database.BeginTransaction())
        {
            var result = context.GetTable<Model.Client>().FirstOrDefault(x => x.ClientId <= 10);
            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 <= 10);
        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();
    }
    View Code

    36. 表变量

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

     1 // 声明表变量
     2 var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo<SqlServerModel.JoinKey>();
     3 context.AddQuery(string.Format("DECLARE {0} [{1}]", typeRuntime.TableName, typeRuntime.TableName.TrimStart('@')));
     4 List<SqlServerModel.JoinKey> keys = new List<SqlServerModel.JoinKey>
     5 {
     6     new SqlServerModel.JoinKey{ Key1 = 2 },
     7     new SqlServerModel.JoinKey{ Key1 = 3 },
     8 };
     9 // 向表变量写入数据
    10 context.Insert<SqlServerModel.JoinKey>(keys);
    11 // 像物理表一样操作表变量
    12 var query =
    13     from a in context.GetTable<Model.Client>()
    14     join b in context.GetTable<SqlServerModel.JoinKey>() on a.ClientId equals b.Key1
    15     select a;
    16 context.AddQuery(query);
    17 // 提交查询结果
    18 List<Model.Client> result = null;
    19 context.SubmitChanges(out result);
    View Code

    【结语】

      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

      

  • 相关阅读:
    非域账户如何连接SQL Server Analysis Service
    Ranet.UILibrary.OLAP
    给Silverlight项目Ranet.UILibrary.OLAP添加客户端调试功能
    编译及安装QCA类库
    关于软件生态环境
    Windows7中操作mysql数据库
    介绍自己
    VS2008技巧收集
    .NET开发不可错过的25款必备工具
    如何做搜索引擎优化(SEO)
  • 原文地址:https://www.cnblogs.com/yiting/p/10952302.html
Copyright © 2011-2022 走看看