13年毕业之际,进入第一家公司实习,接触了 EntityFramework,当时就觉得这东西太牛了,访问数据库都可以做得这么轻松、优雅!毕竟那时还年轻,没见过世面。工作之前为了拿个实习机会混个工作证明,匆匆忙忙学了两个月的 C#,就这样,稀里糊涂的做了程序员,从此走上了一条不归路。那会也只知道 SqlHelper,DataTable。ORM?太高大上,没听说过。虽然在第一家公司只呆了两个月,但让我认识了 EntityFramework,从此也走上了 ORM 的不归路...纯纯的实体,增改删超级简单,查询如行云流水,真心没理由抗拒!以至于后来进入第二家公司做开发极其不适应,因为他们没用 EF,也不用类 linq 的 ORM,他们有自己数据库访问框架。那套东西实体设计复杂,支持的功能少,查询条件还依赖字符串,开发容错率太低,DB操作入口接口设计也很重,里面方法不下60个,看心凉,用心累!那时,好怀念 EF~在新公司工作的时间内,来回都是增改页面,做增删查改,修复BUG,多少有点枯燥乏味,渐渐感觉编码能力提升太慢。同时鉴于用公司的 ORM 也不是很顺手,于是,萌生了自己写 ORM 的念头,再然后...Chloe.ORM 面世了~
Chloe.ORMChloe 查询接口设计借(zhao)鉴(ban) linq,但不支持 linq。开发之前,我给我的 ORM 查询条件接口定义一定要支持lambda表达式(潮流、趋势,在这不讨论表达式树的性能)。开发之初,也有自己设计过查询接口,想了一套又一套,始终没 linq 设计的接口方便,后来,不想了,直接抄 linq,不解释!前人如此伟大设计,不用真对不起他们,我要站在他们的肩膀上!
先看下 IDbContext 接口:
public interface IDbContext : IDisposable { IDbSession CurrentSession { get; } IQuery<T> Query<T>() where T : new(); IEnumerable<T> SqlQuery<T>(string sql, params DbParam[] parameters) where T : new(); T Insert<T>(T entity); object Insert<T>(Expression<Func<T>> body); int Update<T>(T entity); int Update<T>(Expression<Func<T, T>> body, Expression<Func<T, bool>> condition); int Delete<T>(T entity); int Delete<T>(Expression<Func<T, bool>> condition); void TrackEntity(object entity); }
View CodeChloe 操作入口是 IDbContext。IDbContext 仅有两个 Query、两个 Insert、两个 Update 、两个 Delete 和一个 TrackEntity 方法,以及一个 CurrentDbSession 的属性,设计很简单,但绝对能满足81%的需求(多一点满足,多一分热爱)!
这篇文章,主要介绍 Query 接口使用。
实体:
public enum Gender { Man = 1, Woman } [TableAttribute("Users")] public class User { [Column(IsPrimaryKey = true)] [AutoIncrementAttribute] public int Id { get; set; } public string Name { get; set; } public Gender? Gender { get; set; } public int? Age { get; set; } public int? CityId { get; set; } public DateTime? OpTime { get; set; } } public class City { [Column(IsPrimaryKey = true)] public int Id { get; set; } public string Name { get; set; } public int ProvinceId { get; set; } } public class Province { [Column(IsPrimaryKey = true)] public int Id { get; set; } public string Name { get; set; } }
View Code首先,创建一个 DbContext:
IDbContext context = new MsSqlContext(DbHelper.ConnectionString);
再创建一个 IQuery<T>:
IQuery<User> q = context.Query<User>();
基本查询
IQuery<User> q = context.Query<User>(); q.Where(a => a.Id > 0).FirstOrDefault(); q.Where(a => a.Id > 0).ToList(); q.Where(a => a.Id > 0).OrderBy(a => a.Age).ToList(); q.Where(a => a.Id > 0).Take(999).OrderBy(a => a.Age).ToList(); //分页。避免生成的 sql 语句太长占篇幅,只选取 Id 和 Name 两个字段 q.Where(a => a.Id > 0).OrderBy(a => a.Age).ThenByDesc(a => a.Id).Select(a => new { a.Id, a.Name }).Skip(1).Take(999).ToList(); /* * SELECT TOP (999) [T].[Id] AS [Id],[T].[Name] AS [Name] FROM (SELECT [Users].[Id] AS [Id],[Users].[Name] AS [Name],ROW_NUMBER() OVER(ORDER BY [Users].[Age] ASC,[Users].[Id] DESC) AS [ROW_NUMBER_0] FROM [Users] AS [Users] WHERE [Users].[Id] > 0) AS [T] WHERE [T].[ROW_NUMBER_0] > 1 */ //如果需要多个条件的话 q.Where(a => a.Id > 0).Where(a => a.Name.Contains("lu")).ToList(); /* * SELECT [Users].[Id] AS [Id],[Users].[Name] AS [Name],[Users].[Gender] AS [Gender],[Users].[Age] AS [Age],[Users].[CityId] AS [CityId],[Users].[OpTime] AS [OpTime] FROM [Users] AS [Users] WHERE ([Users].[Id] > 0 AND [Users].[Name] LIKE '%' + N'lu' + '%') */ //选取指定字段 q.Select(a => new { a.Id, a.Name, a.Age }).ToList(); //或者 q.Select(a => new User() { Id = a.Id, Name = a.Name, Age = a.Age }).ToList(); /* * SELECT [Users].[Id] AS [Id],[Users].[Name] AS [Name],[Users].[Age] AS [Age] FROM [Users] AS [Users] */
View Code 连接查询建立连接: