Chloe.ORM 是国人开发的一款数据库访问组件,很是简单易用。目前支持四种主流数据库:SqlServer、MySQL、Oracle,以及Sqlite,作者为这四种数据库划分出了各自对应的组件程序集,以 MySQL 为例即 Chloe.MySql.dll,其他以此类推,可以同时引用这些程序集从而在一个项目中访问多种数据库,另外 Chloe 用的是 Emit 生成 IL 代码,这样避免了反射机制造成的性能损耗。

Chloe 的文档对基础操作列举得很全面,我就针对实践中的一些应用体会做些记录,也当是备忘后查。

一、基于工厂模式多数据库访问机制的构建

1、数据库访问连接串

定义在 appSettings 节点下。

DefaultDb 表示在构建数据库连接对象时,采用默认方式使用的数据库类型。

MySQLConnectionString 和 OracleConnectionString 表示针对指定数据库的默认连接字符串。

2、数据库类型枚举

///

/// 数据库类型

///

public enum DatabaseType

{

MySQL = 1,

Oracle = 2

}

如果需要,可以继续追加 SqlServer 和 Sqlite。

3、数据库连接工厂接口

using System.Data;

namespace Chloe.Infrastructure

{

public interface IDbConnectionFactory

{

IDbConnection CreateConnection();

}

}

注:该接口在 Chloe 的底层已为我们定义好了。

4、面向具体数据库工厂类的实现

///

/// 针对 MySQL 数据库的连接工厂类

///

public class MySqlConnectionFactory : IDbConnectionFactory

{

string _connString = string.Empty;

public MySqlConnectionFactory()

{

this._connString = "server=192.168.120.68; port=3306; User Id=sa; password=123456sa; database=OrderAutoCategory; charSet=utf8;";

}

public MySqlConnectionFactory(string connString)

{

this._connString = connString;

}

public IDbConnection CreateConnection()

{

MySqlConnection conn = new MySqlConnection(this._connString);

return conn;

}

}

///

/// 针对 Oracle 数据库的连接工厂类

///

public class OracleConnectionFactory : IDbConnectionFactory

{

string _connString = string.Empty;

public OracleConnectionFactory()

{

this._connString = @"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=228.10.135.8)(PORT=1521)))(CONNECT_DATA=(SID=orcl2)));User Id=sa;Password=123456sa;Pooling=true;MAX Pool Size=20;Min Pool Size=2;Connection Lifetime=20;Connect Timeout=20;";

}

public OracleConnectionFactory(string connString)

{

this._connString = connString;

}

public IDbConnection CreateConnection()

{

OracleConnection oracleConnection = new OracleConnection(this._connString);

OracleConnectionDecorator conn = new OracleConnectionDecorator(oracleConnection);

return conn;

}

}

出于修改 DbCommand 参数绑定方式的目的,作者定义了一个装饰类 OracleConnectionDecorator,在项目实践中我们直接从官网复制过来使用即可。

5、用以构建 IDbContext 实例的自定义工厂类

using System;

using System.Configuration;

using Chloe;

using Chloe.Infrastructure.Interception;

using Chloe.MySql;

using Chloe.Oracle;

namespace Pro.Factory

{

public class DbContextFactory

{

public static IDbContext CreateDbContext()

{

// 数据库类型

DatabaseType dbType = GetDatabaseType(ConfigurationManager.AppSettings["DefaultDb"]);

// 连接字符串

string connectionString = GetConnectionString(dbType);

return CreateDbContext(dbType, connectionString);

}

public static IDbContext CreateDbContext(DatabaseType dbType)

{

string connectionString = GetConnectionString(dbType);

return CreateDbContext(dbType, connectionString);

}

public static IDbContext CreateDbContext(string connectionString)

{

DatabaseType dbType = GetDatabaseType(ConfigurationManager.AppSettings["DefaultDb"]);

return CreateDbContext(dbType, connectionString);

}

public static IDbContext CreateDbContext(DatabaseType dbType, string connectionString)

{

IDbContext context = null;

switch (dbType)

{

case DatabaseType.MySQL:

context = new MySqlContext(new MySqlConnectionFactory(connectionString));

break;

case DatabaseType.Oracle:

context = new OracleContext(new OracleConnectionFactory(connectionString));

break;

default:

throw new Exception("在工厂 DbContextFactory 中试图创建 IDbContext 时,发现数据库类型不明确(考虑遗漏了类型)");

}

IDbCommandInterceptor interceptor = new DbCommandInterceptor();

// 全局拦截器

//DbInterception.Add(interceptor);

// 单个DbContext拦截器

if (context != null)

{

context.Session.AddInterceptor(interceptor);

}

return context;

}

/* 公共函数 */

public static string GetConnectionString(DatabaseType dbType)

{

string connectionString = "";

switch (dbType)

{

case DatabaseType.MySQL:

connectionString = ConfigurationManager.AppSettings["MySQLConnectionString"];

break;

case DatabaseType.Oracle:

connectionString = ConfigurationManager.AppSettings["OracleConnectionString"];

break;

default:

throw new Exception("在工厂 DbContextFactory 中试图创建 IDbContext 时,发现数据库类型不明确(考虑遗漏了类型)");

}

if (string.IsNullOrEmpty(connectionString))

{

throw new Exception(string.Format(@"基于 {0} 数据库的连接字符串为空,需进行配置", dbType.ToString()));

}

return connectionString;

}

public static DatabaseType GetDatabaseType(string dbTypeName)

{

if (string.IsNullOrEmpty(dbTypeName))

{

throw new Exception("需配置默认数据库类型 DefaultDb ");

}

DatabaseType dbType = (DatabaseType)Enum.Parse(typeof(DatabaseType), dbTypeName);

return dbType;

}

}

}

上述代码的核心方法为 CreateDbContext,共提供了 4 个重载。

第一个无参数重载方法表示一切按默认的配置项进行初始化,从其代码可以看到,“数据库类型”是由配置节点的 DefaultDb 决定,然后调用了 GetConnectionString 方法来确立“连接字符串”,它会针对不同种类数据库安排一个默认的连接。

第二个重载方法要求提供“数据库类型”,然后直接调用 GetConnectionString 来确立“连接字符串”即可。

第三个重载方法要求提供“连接字符串”,那么“数据库类型”是由配置节点的 DefaultDb 决定。

第四个重载方法要求提供“数据库类型”和“连接字符串”,在调用时要确保这两个参数的值是统一的,即如果“数据库类型”是 MySQL 的话,那么“连接字符串”也必须是基于 MySQL 数据库。

另外,在第四个重载方法中还实现了拦截器功能,目的在于截取 SQL 语句,以备后查。

二、实体类解析

[Table("OrderDistributeRouteConfigCode")]

public class RouteConfigCode

{

[NonAutoIncrement]

[Column(IsPrimaryKey = true, Name = "Guid")]

public string Guid { get; set; }

[NotMapped]

public string DistributeSiteName { get; set; }

}

列举一下四个最常用的特性:

Table 为表名映射,对应数据库表名

Column 为列名映射,对应数据库列名

NonAutoIncrement 表示该列为“非自增长”,意味着开发者要自行赋值

NotMapped 表示该列不与任何表字段进行映射,比如在统计时,当某属性是通过二次计算得来时则可以标识该特性。

三、增删改查

1、新增

public BaseResult Add(RouteConfigCodeEdit edit)

{

BaseResult result = BaseResult.Fail();

DateTime currentDatetime = DateTime.Now;

using (IDbContext dbContext = DbContextFactory.CreateDbContext())

{

try

{

dbContext.Session.BeginTransaction();

RouteConfigCode entity = new RouteConfigCode();

entity.OrderDistributeRouteConfigGuid = edit.OrderDistributeRouteConfigGuid;

entity.SiteCode = edit.SiteCode;

entity.SiteName = edit.SiteName;

entity.OrderType = edit.OrderType;

entity.IsMQ = edit.IsMQ;

entity.Remarks = edit.Remarks;

entity.IsEnable = edit.IsEnable;

entity.Guid = Guid.NewGuid().ToString();

entity.CreateTime = currentDatetime;

entity.LastUpdateTime = currentDatetime;

dbContext.Insert(entity);

dbContext.Session.CommitTransaction();

result.Status = true;

result.StatusMessage = "新增成功";

}

catch (Exception ex)

{

dbContext.Session.RollbackTransaction();

NLogHelper.Error(ex);

result.StatusMessage = ex.Message;

}

}

return result;

}

整个业务逻辑操作都囊括在 using 块中,这样确保由 DbContextFactory 工厂构建的 IDbContext 连接对象可以及时的被关闭和销毁。

紧接着,拟定 try/catch 来分管期望与意外这两种情形,如果所有业务操作都在期望之中则正常提交事务(Commit),并返回相关状态为 true;如果操作期间发生了不可预测的意外情形,则通过 catch 块来捕获异常,首当其冲是回滚事务(Rollback),然后记录文本日志(txt),并返回异常内容给调用方。

使用基于 Insert 方法可以做到参数化,要注意的是它会把实体中所有的属性组织到 SQL 语句中。

2、修改

public BaseResult Update(RouteConfigCodeEdit edit)

{

BaseResult result = BaseResult.Fail();

DateTime currentDatetime = DateTime.Now;

using (IDbContext dbContext = DbContextFactory.CreateDbContext())

{

try

{

dbContext.Session.BeginTransaction();

RouteConfigCode entity = dbContext.Query().Where(p => p.Guid == edit.Guid).FirstOrDefault();

if (entity != null)

{

dbContext.TrackEntity(entity);

entity.Guid = edit.Guid;

entity.OrderDistributeRouteConfigGuid = edit.OrderDistributeRouteConfigGuid;

entity.SiteCode = edit.SiteCode;

entity.SiteName = edit.SiteName;

entity.OrderType = edit.OrderType;

entity.IsMQ = edit.IsMQ;

entity.Remarks = edit.Remarks;

entity.IsEnable = edit.IsEnable;

entity.LastUpdateTime = currentDatetime;

int effectedRows = dbContext.Update(entity);

result.Status = true;

result.StatusMessage = "修改成功";

}

else

{

result.Status = false;

result.StatusMessage = "修改失败,记录不存在";

}

dbContext.Session.CommitTransaction();

}

catch (Exception ex)

{

dbContext.Session.RollbackTransaction();

NLogHelper.Error(ex);

result.StatusMessage = ex.Message;

}

}

return result;

}

修改操作的重点在于属性跟踪,为避免不必要的属性更新,我们应尽量只更新那些发生了变化的属性,或者说被修改过的属性,所以为属性赋值之前就需要调用一次 TrackEntity 方法,最后才是调用 Update 方法,该方法支持参数化处理。

3、删除

public BaseResult Delete(string ids)

{

DateTime currentDatetime = DateTime.Now;

BaseResult result = BaseResult.Error("操作失败,");

using (IDbContext dbContext = DbContextFactory.CreateDbContext())

{

try

{

dbContext.Session.BeginTransaction();

// 批量操作时累计受影响行数

int total = 0;

string[] idArray = ids.Split(",");

foreach (string id in idArray)

{

RouteConfigCode entity = new RouteConfigCode();

entity.Guid = id;

int effectedRows = dbContext.Delete(entity);

if (effectedRows > 0)

{

total += effectedRows;

}

}

dbContext.Session.CommitTransaction();

result.Status = true;

result.StatusMessage = string.Format("操作成功,总记录:{0},执行成功:{1}", idArray.Length, total);

}

catch (Exception ex)

{

dbContext.Session.RollbackTransaction();

NLogHelper.Error(ex);

result.StatusMessage += ex.Message;

}

}

return result;

}

实例化一个对象,并对主键列赋值,然后传递给 Delete 方法即可,该方法支持参数化处理。

4、分页查询

分页 Pager:

public class Pager

{

public int totalRows { set; get; }

public int pageSize { set; get; }

public int pageNo { set; get; }

public int totalPages { set; get; }

public string direction { set; get; }

public string sort { set; get; }

public object rows { set; get; }

public Pager()

{

totalRows = 0;

pageSize = 20;

pageNo = 1;

totalPages = 0;

}

}

业务查询实体:

public class RouteConfigCodeSearch

{

public Pager Pager { get; set; }

public string SiteCode { get; set; }

public string SiteName { get; set; }

}

业务查询实体除了包含 Pager 之外还包含了查询栏里的各项条件,比如按编号(SiteCode)、按名称(SiteName)。

分页查询:

public List GetListByPage(RouteConfigCodeSearch search)

{

List routeConfigCodeList = new List();

using (IDbContext dbContext = DbContextFactory.CreateDbContext())

{

var query = dbContext.Query()

.LeftJoin((code, routeConfig) => code.OrderDistributeRouteConfigGuid == routeConfig.Guid)

.Select((code, routeConfig) => new RouteConfigCode

{

DistributeSiteName = routeConfig.DistributeSiteName,

Guid = code.Guid,

OrderDistributeRouteConfigGuid = code.OrderDistributeRouteConfigGuid,

SiteCode = code.SiteCode,

SiteName = code.SiteName,

OrderType = code.OrderType,

Remarks = code.Remarks,

CreateTime = code.CreateTime,

LastUpdateTime = code.LastUpdateTime,

IsEnable = code.IsEnable,

IsMQ = code.IsMQ

});

#region 查询条件

if (!string.IsNullOrEmpty(search.SiteCode))

{

query = query.Where(p => p.SiteCode.Contains(search.SiteCode));

}

if (!string.IsNullOrEmpty(search.SiteName))

{

query = query.Where(p => p.SiteName.Contains(search.SiteName));

}

#endregion

routeConfigCodeList = query.OrderBy(p => p.CreateTime).TakePage(search.Pager.pageNo, search.Pager.pageSize).ToList();

search.Pager.totalRows = query.Count();

}

return routeConfigCodeList;

}

通过 TakePage 方法就可以很方便的实现分页功能了,同时把总记录数赋给 totalRows 属性以告知调用者。

5、单条查询

public BaseResult GetItemById(string id)

{

JsonResult result = new JsonResult();

using (IDbContext dbContext = DbContextFactory.CreateDbContext())

{

try

{

RouteConfigCode entity = dbContext.Query().Where(p => p.Guid == id).FirstOrDefault();

if (entity == null)

{

result.Status = false;

result.StatusMessage = "查询记录失败";

}

else

{

result.Data = entity;

}

}

catch (Exception ex)

{

NLogHelper.Error(ex);

result.Status = false;

result.StatusMessage = ex.Message;

}

}

return result;

}

通过 FirstOrDefault 可以确保只查询一条记录,如果找不到则返回 null。

在使用 Chloe.ORM 的过程中总体感觉非常顺畅,满足了简单、易用的图快心理,重点是作者很热心,在QQ群里发问他都能及时回复。园友们也可以尝试用用看。

chloe.mysql_Chloe.ORM框架应用实践相关推荐

  1. EF、Chloe、SqlSugar、DOS.ORM四种ORM框架的对比

    文章目录 四种orm框架的对比 1.什么是ORM? 2.四种框架的基本信息对比如下表: 3.四种框架的耗时情况如下: 4.四种框架都支持哪些功能? 5.就个人使用而言,比较推荐哪个框架? 6.SqlS ...

  2. .NET(C#)有哪些主流的ORM框架,FreeSql,SqlSugar,Dapper,EF还是...

    前言 在以前的一篇文章中,为大家分享了<什么是ORM?为什么用ORM?浅析ORM的使用及利弊>.那么,在目前的.NET(C#)的世界里,有哪些主流的ORM,FreeSql,SqlSugar ...

  3. 论ORM框架—EntityFrameworkCore

    欢迎大家阅读<朝夕Net社区技术专刊> 我们致力于.NetCore的推广和落地,为更好的帮助大家学习,方便分享干货,特创此刊!很高兴你能成为忠实读者,文末福利不要错过哦! 01 PART ...

  4. NET主流ORM框架分析

    接上文我们测试了各个ORM框架的性能,大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异.这里和大家分享下我对ORM框架的理解及一些使用经验. ORM框架工作原理 所有的OR ...

  5. .NET(C#)有哪些主流的ORM框架

    前言 在以前的一篇文章中,为大家分享了<什么是ORM?为什么用ORM?浅析ORM的使用及利弊>.那么,在目前的.NET(C#)的世界里,有哪些主流的ORM,SqlSugar,Dapper, ...

  6. .NET主流的ORM框架

    C# .NET主流ORM框架举例: 1.FreeSql(国内) 2.SqlSugar (国内) 3.Dos.ORM (国内) 4.Chloe (国内) 5.StackExchange/Dapper ( ...

  7. python orm框架

    python orm框架是一个数据处理框架,它提供了许多有用的工具,包括: 1.使用 pandas库对数据进行预处理,如:添加标签.删除重复值.转换为表格样式等. 2.使用 sql语句进行数据的增删改 ...

  8. .Net 常用的ORM框架

    orm主要有几个: sugar:http://www.17ky.net/soft/634.html Chloe.ORM:http://www.17ky.net/soft/554.html Cyqdat ...

  9. 第一章:ORM框架发展历程和MyBatis的核心应用

    ORM框架的发展历史与MyBatis的高级应用 一.ORM框架的发展历程 1. JDBC操作 1.1 JDBC操作的特点 最初的时候我们肯定是直接通过jdbc来直接操作数据库的,本地数据库我们有一张t ...

  10. 吉特仓库管理系统-ORM框架的使用

    最近在园子里面连续看到几篇关于ORM的文章,其中有两个印象比较深刻<<SqliteSugar>>,另外一篇文章是<<我的开发框架之ORM框架>>, 第一 ...

最新文章

  1. as工程放到源码编译_Android 7.1源码编译导入AS完整教程
  2. [JS-DOM]DOM概述
  3. 支付宝沙箱环境下模拟下单流程
  4. Adobe 修复严重的 Photoshop 缺陷
  5. W Zong / A Robust Open-source Algorithm to Detect Onset and Duration of QRS Complexes
  6. 【JUC】JDK1.8源码分析之ReentrantReadWriteLock(七)
  7. 决定明智地放弃对名手旋风等象棋引擎的破解...
  8. [Accessibility] ****************** Loading GAX Client Bundle ****************
  9. python就业方向有哪些?
  10. 4.1.14 Flink-流处理框架-Flink流处理API之数据重分区操作
  11. 2022年四川省职业院校技能大赛(中职组)网络安全赛项规程
  12. rstudio中读取数据_用RStudio导入数据
  13. ie浏览器点击无法打开问题【亲测有效哦】
  14. Python求解江苏小升初数学题与图像阴影绘制
  15. 30s快速开通微商城,零售+分销结合,支持直播美颜
  16. 客户体验改善计划的用户注销通知导致服务器自动重启
  17. fms安装教程 linux_[转]linux下fms2流媒体服务器搭建之三-----FMS安装篇
  18. 计算机图形学三:光栅化-Rasterization
  19. 权威典藏版:漫游费的前世今生(上)
  20. 计算机维护维修论文摘要,计算机维护论文摘要怎么写 计算机维护论文摘要范文参考...

热门文章

  1. 计算机毕业设计springboot+vue+elementUI高校志愿者管理系统(源码+系统+mysql数据库+Lw文档)
  2. 跳楼机(同余类最短路)
  3. 曙光服务器如何重新设置u盘启动_u盘装曙光服务器 曙光服务器进bios设置u盘启动...
  4. 分布式系统故障容灾治理总结
  5. 初窥 Python 的 import 机制
  6. iOS 之强大的WebSocket
  7. [产品经理]产品经理的职责
  8. 服务器共享文件设成禁止删除,服务器共享文件夹权限 禁止删除共享文件方法...
  9. 信息奥赛一本通1196:踩方格
  10. 电脑管家软件搬家没有历史记录