答:ORM(Object-relational mapping)即对象关系映射,是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。也就是说,ORM是通过使用描述对象和数据库之间映射的元数据(映射文件信息),将程序中的对象自动持久化到关系数据库中。说白了就是将相应的实体映射到相应的数据库表,然后使用orm框架封装好的api进行数据库访问,减少了自己写数据库访问类的步骤。
2、ORM框架的优缺点是?
答:ORM框架的优点:(1)操作简单,提高开发效率。(2)支持面向对象封装。(3)可移植。(4)减少重复性代码
ORM框架的缺点:(1)处理多表联查之类的查询时,ORM的语法会变得很复杂。(2)执行性能较低(但现在有一些轻型ORM框架,性能接近原生SQL)。
框架/对比属性 | SqlSugar | Dos.ORM | Chloe | EFCodeFirst |
---|---|---|---|---|
支持数据库类型 | MySql、SqlServer、Sqlite、Oracle 、 postgresql | MySql、SqlServer、Sqlite、Oracle 等数据库 | MySql、SqlServer、Sqlite、Oracle 、 postgresql | MySql、SqlServer、Sqlite、Oracle 、 postgresql |
支持的平台版本 | .net和net core | .net和net core | .net和net core | .net和net core |
团队规模 | 少于10人 | 公司性质 | 未知 | 微软 |
体积 | 895k(下载后package的大小) | 607k(下载后package的大小) | 558k(下载后package的大小) | 17.8M |
文档帮助 | 较全(install后,就可以直接使用了) | 一般(但是很多细节的东西并没有告知用户,例如需要通过代码生成器生成的实体类才能与数据库进行映射) | 较全(install后,创建数据库即可直接使用) | 较全(无论是微软官方还是百度谷歌,用的人比较多,遇到问题容易) |
与数据库交互方式 | 支持dbfirst、codefirst | 支持dbfirst | 支持dbfirst | 支持code first(当前使用的是code first,也可支持dbfirst) |
学习成本 | 低 | 一般 | 低 | 较高(刚开始使用会遇到许多的bug,虽然网上都有解决方法,但是学习起来没前几种容易) |
如下表格,展示的是四种ORM框架Crud的性能,其中,(1)增查删改都是循环5次,每次增删改1万条数据,查询是每次查询10万条数据,取5次的平均值;(2)批量增删改都是循环5次,每次增删改10万条数据,取5次平均值:
类别/框架名称 | Chloe(单位:秒) | DOS.ORM(单位:秒) | EF(Code First)(单位:秒) | SqlSugar(单位:秒) |
---|---|---|---|---|
新增(Insert) | 13.9063 | 13.5712 | 273.563 | 12.4268 |
删除(Delete) | 13.6688 | 13.3366 | 65.1328 | 12.4202 |
修改(Update) | 14.3704 | 14.3306 | 54.021 | 12.084 |
查询(Select) | 1.7502 | 0.2308 | 0.5486 | 0.1416 |
批量新增(BulkInsert) | 1.4382秒 | 20.6162秒 | 27.6674秒 | 2.7286秒 |
批量修改(BulkUpdate) | 0.5988秒(不足以用来参照,看下面注解) | 22.6556秒 | 22.1634秒 | 8.8188秒 |
批量删除(BulkDelete) | 0.7504秒(不足以用来参照,看下面注解) | 只能批量删除2009条,超过就报错 | 20.336秒 | 5.7034秒 |
由上表可知,各种框架CRUD的性能如下(由快到慢):
(1)循环CRUD操作的性能如下:
新增:SqlSugar>DOS.ORM>Chloe>EF
删除:SqlSugar>DOS.ORM>Chloe>EF
修改:SqlSugar>DOS.ORM>Chloe>EF
查询:SqlSugar>DOS.ORM>EF>Chloe
综上可知:SqlSugar框架的CRUD性能是最高的,其中EF除了查询比较快之外,删改所花费的时间都是其他三种框架的4~5倍,而新增就是20倍左右!
(2)循环批量CRUD的性能如下:
批量新增:Chloe>SqlSugar>DOS.ORM>EF
批量修改:Chloe>SqlSugar>EF>DOS.ORM
批量删除:Chloe>SqlSugar>EF
注解1:Chloe是有批量新增的方法BulkInsert,故其批量新增操作与其他框架一样。但是,Chloe没有批量修改、删除的方法,如下代码片段:
//下面的n表示1~5,是循环执行的次数,在上面的Insert步骤中分配插入了1万条"Chloe测试的数据1"、"Chloe测试的数据2"、"Chloe测试的数据3"、"Chloe测试的数据4"、"Chloe测试的数据5"
//Chloe只能通过lamdba表达式匹配到的数据进行删改,而不能直接在update()中添加一个list
context.Update(a => a.Name == "Chloe测试的数据" + n, a => new ORMTest()
{
Name = "Chloe修改的数据" + n
});
context.Delete(a => a.Name == "Chloe修改的数据" + n);
注解2:DOS.ORM批量删除超过2009条数据时就会报错,如下图:
综上,只有SqlSugar涵盖的方法比较多,而且速度也较快!
功能/框架 | Chloe | DOS.ORM | EF | SqlSugar |
---|---|---|---|---|
增删查改 | 支持 | 支持 | 支持 | 支持 |
批量增删改 | 支持 | 支持 | 支持 | 支持 |
事务、存储过程、日志 | 支持 | 支持 | 支持 | 支持 |
lamdba、执行SQL | 支持 | 支持 | 支持 | 支持 |
linq | 不支持 | 不支持 | 支持 | 不支持 |
多表查询、分组查询 | 支持 | 支持 | 支持 | 支持 |
全局过滤器 | 不支持 | 不支持 | 支持 | 支持 |
答:四种框架都支持:
基本查询、多表查询、分组查询、批量增删改操作、存储过程、事务、执行SQL、日志等功能。
答:个人比较推荐SqlSugar,原因如下:
(1)只要下载了SqlSugar包后,就可以直接按照官网的例子进行编码,日志跟踪方面我认为是最简单已用的,且文档写得比较好、可由代码生成数据库,可以快速上手。
(2)Chloe与SqlSugar差不多,但是由于我觉得SqlSugar日志跟踪方面做得比较好且可以由代码生成数据库,且Chloe对批量操作的支持不是很好,只能批量新增(且没有返回值),不能批量删除、修改,所以我才选择SqlSugar:
(3)Dos.ORM是这三个框架里面最不好上手,***不能***直接自己创建类文件,而是需要下载官网推荐的***代码生成器***去生成相应的类,然后才能进行数据库的访问,否则插入删除等操作都会报错,所以就个人而言,不推荐用这个,认为学习成本比其他两个高。
(4)EF是重量级ORM框架,上面三种框架有的功能它都有,且有微软这个大厂在背后支撑,百度谷歌可以轻易搜索到大多数问题的解决方法,一开始,只要修改类结构,容易遇到与"dbo.Migrationary"相关的错误(这是需要了解codefirst数据库迁移方面的知识,可通过这边文章了解https://blog.csdn.net/xwnxwn/article/details/90171519),如果想用的功能不多,且不想框架太大的话,就还是推荐上面三种。
(5)四种框架中,SqlSugar进行CRUD的性能最高,而EF最慢。
(1)在nuget中输入Install-Package sqlSugar或nuget管理工具中搜索sqlSugar,下载sqlSugar包
(2)简单的实例
相应的实体类:
public class Student
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
[SugarColumn(IsNullable=true)]
public int? ClassessId { get; set; }
public override string ToString()
{
return this.Name + "的id为:" + this.Id + ",年龄为:" + this.Age;
}
}
public class Classess
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
}
public class ORMTest
{
public int Id { get; set; }
public string Name { get; set; }
}
实例代码:
using SqlSugar;
using System;
using System.Configuration;
namespace SqlSugarTest
{
class Program
{
public static SqlSugarClient GetInstance()
{
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
//ConnectionString = Config.ConnectionString,//数据库连接字符串
ConnectionString = connStr,
DbType = DbType.SqlServer,//数据库类型
IsAutoCloseConnection = true,////自动释放数据务,如果存在事务,在事务结束后释放
InitKeyType = InitKeyType.Attribute//从实体特性中读取主键自增列信息
});
//关闭日志打印
//db.Aop.OnLogExecuting = (sql, pars) =>
//{
// Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
// Console.WriteLine();
//};
return db;
}
//static string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
static string connStr = "server=DESKTOP-TROTQO7;uid=sa;pwd=123456;database=SqlSugarTest";
static void Main(string[] args)
{
var db = GetInstance();
#region 使用代码优先的方法创建数据库表
//使用Code first的方法,需要使用CreateDatabase方法创建数据库
//db.DbMaintenance.CreateDatabase();//创建数据库
//db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(Student));//根据实体类创建数据库表
//db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(Classess));//根据实体类创建数据库表
#endregion
#region 使用数据库优先的方法,根据数据库表生成相应的类文件
//注意:使用DbFirst数据库账户要有系统表的权限,否则无法读取表的结构
//1.将库里面所有表都生成实体类文件
//var modelStr = db.DbFirst.ToClassStringList();//根据数据库的表生成类字符串
//将数据库表生成相应的实体类,并存储到相应的路径中,SqlSugarTest表示生成的类的命名空间
//db.DbFirst.CreateClassFile("d:\\Demo", "SqlSugarTest");
#endregion
#region 插入(Insert)
//向student表中插入单条数据
//int result = db.Insertable(new Student { Name = "王五强", Age = 26 }).ExecuteCommand();
//向student表中批量插入数据
//var insertList = new Student[]
//{
// new Student { Name = "小明", Age = 16,ClassessId=1 },
// new Student { Name = "小红", Age = 18 ,ClassessId=1},
// new Student { Name = "小刚", Age = 20,ClassessId=2 },
// new Student { Name = "小刚", Age = 20,ClassessId=2 }
//};
//int result2 = db.Insertable(insertList).ExecuteCommand();//向student表中插入数据
//var insertList2 = new Classess[]
//{
// new Classess { Name = "一年一班", },
// new Classess { Name = "二年一班"},
//};
//int result3 = db.Insertable(insertList2).ExecuteCommand();//向student表中插入数据
#endregion
#region 查询(Select)
//InSingle中填的是数据的id,如果数据不存在,则返回null
//var model = db.Queryable().InSingle(1);//查询单条数据
////First返回当前数据库表的第一条数据
//var model2 = db.Queryable().First();//获取第一条数据
//var selectList = db.Queryable().ToList();//查询所有数据
////分页查询
//int totalCount = 0, totalPage = 0;
//var pageList = db.Queryable().ToPageList(2, 2, ref totalCount, ref totalPage);
#endregion
#region 分组和多表查询
//var group = db.Queryable().GroupBy(it => it.ClassessId).Select(it => new { id = SqlFunc.AggregateCount(it.Id) }).ToList();
//var joinList = db.Queryable((st, cs) => new JoinQueryInfos(JoinType.Left, st.ClassessId == cs.Id))
//.OrderBy((st, cs) => cs.Id, OrderByType.Desc)//通过班级id排序
//.OrderBy(st => st.Id, OrderByType.Desc)//通过学生id排序
//.Select((st, cs) => new { StuName = st.Name, ClassName = cs.Name })
//.ToList();
#endregion
#region 修改(Update)
//修改单条数据
//int updateResult = db.Updateable(new Student { Id=1,Name="sdfjdskjflk", Age = 18 }).ExecuteCommand();
//查询出相应的实体再进行修改
//UpdateColumns执行修改某一列,IgnoreColumns忽略某一列不进行更新操作,具体操作请看官方文档
//var updateModel = db.Queryable().InSingle(2);
//updateModel.Name = "我是修改的"+DateTime.Now;
//int updateResult32= db.Updateable(updateModel).ExecuteCommand();
////批量修改数据
//var list = db.Queryable().Take(5).ToList();
//foreach (var item in list)
//{
// item.Name += DateTime.Now;
//}
//var manyResult = db.Updateable(list).ExecuteCommand();
#endregion
#region 删除(Delete)
//根据实体删除数据
//db.Deleteable(new Student() { Id = 1 }).ExecuteCommand();
//删除id=1的数据,返回删除成功的条数
//db.Deleteable().In(1).ExecuteCommand();
//根据id批量删除数据
//db.Deleteable().In(new int[] { 1, 2 }).ExecuteCommand();
//也可以先查询出来一些数据进行批量删除,并通过sql语句的方式获取前五的数据
//var deleteList = db.SqlQueryable("select top 5 * from Student").ToList();
//var deleteResult = db.Deleteable(deleteList).ExecuteCommand();
#endregion
#region 事务
//想体验事务的回滚,就去掉下面代码的注释
//try
//{
// db.Ado.BeginTran();
// var insertList = new Student[]
// {
// new Student { Name = "小明", Age = 16 },
// new Student { Name = "小红", Age = 18 },
// new Student { Name = "小刚", Age = 20 }
// };
// int result2 = db.Insertable(insertList).ExecuteCommand();//向student表中插入数据
// //创建一个班级类,并且不映射到数据库中,以此来造成插入抛异常,实现事务的回滚操作
// var cModel = new Classess()
// {
// Id = 1,
// Name = "一年一班"
// };
// db.Insertable(cModel).ExecuteCommand();//向classes表中插入数据
// db.Ado.CommitTran();
//}
//catch (Exception ex)
//{
// db.Ado.RollbackTran();
// throw ex;
//}
#endregion
#region 性能测试
//测试新增10万条数据花的时间
//Stopwatch watch = new Stopwatch();
//watch.Start();
//int circleCount = Convert.ToInt32(ConfigurationManager.AppSettings["circleCount"]);
//int count = 1;
//for (int i = 1; i <= circleCount; i++)
//{
// var insertList = new ORMTest[]
// {
// new ORMTest { Name = "小明", Id=count++},
// new ORMTest { Name = "小红", Id=count++ },
// new ORMTest { Name = "小刚", Id=count++ },
// new ORMTest { Name = "小气", Id=count++ },
// new ORMTest { Name = "小兰", Id=count++},
// new ORMTest { Name = "小七", Id=count++},
// new ORMTest { Name = "小小", Id=count++ },
// new ORMTest { Name = "小五", Id=count++},
// new ORMTest { Name = "小六", Id=count++ },
// new ORMTest { Name = "零零七", Id=count++ }
// };
// int result2 = db.Insertable(insertList).ExecuteCommand();//向student表中插入数据
//}
//watch.Stop();
//Console.WriteLine("插入10万条数据花的时间为:" + Convert.ToDouble(watch.ElapsedMilliseconds) / 1000 + "秒");
//查询10完数据花费的时间,循环100次
//Stopwatch watch = new Stopwatch();
//int count = Convert.ToInt32(ConfigurationManager.AppSettings["circleCount"]);
//watch.Start();
//for (int i = 0; i < count; i++)
//{
// var list = db.Queryable().ToList();
//}
//watch.Stop();
//double useTime = Convert.ToDouble(watch.ElapsedMilliseconds) / 1000;
//Console.WriteLine("SqlSugar查询10万条数据花的时间为:" + useTime + "秒");
//double sum = 0;
//int count = Convert.ToInt32(ConfigurationManager.AppSettings["circleCount"]);
//for (int i = 1; i <= count; i++)
//{
// Stopwatch watch = new Stopwatch();
// watch.Start();
// var list = db.Queryable().ToList();
// watch.Stop();
// double useTime = Convert.ToDouble(watch.ElapsedMilliseconds) / 1000;
// sum += useTime;
// Console.WriteLine($"SqlSugar第{i}次查询10万条数据花的时间为:" + useTime + "秒");
//}
//Console.WriteLine($"SqlSugar循环{count}次查询十万条数据的平均耗时为:" + sum/count+"秒");
#endregion
Console.ReadKey();
}
///
/// 数据库实例化类
///
///
private static SqlSugarClient GetInstance()
{
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
//ConnectionString = Config.ConnectionString,//数据库连接字符串
ConnectionString = connStr,
DbType = DbType.SqlServer,//数据库类型
IsAutoCloseConnection = true,////自动释放数据务,如果存在事务,在事务结束后释放
InitKeyType = InitKeyType.Attribute//从实体特性中读取主键自增列信息
});
//关闭日志打印
//db.Aop.OnLogExecuting = (sql, pars) =>
//{
// Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
// Console.WriteLine();
//};
return db;
}
}
(1)在nuget中输入Install-Package Chloe.SqlServer或nuget管理工具中搜索Chloe.SqlServer,下载Chloe包
(2)Chloe的简单实例(有批量新增,但无批量删除的函数,且批量修改会有问题,批量处理数据方面不是很好)
相应的实体类:
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; }
}
public enum Gender
{
Man = 1,
Woman
}
[Table("Users")]
public class User
{
//Chloe.ORM 亦支持 Fluent Mapping,自带有一些简单的,如下
[Column(IsPrimaryKey = true)]
//[AutoIncrement]
[NonAutoIncrementAttribute]//标记为非自动增长
public string Id { get; set; }
[Column(Size =100)]//字符长度
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; }
[NotMappedAttribute]//设置remark列不映射到数据库
public string Remark { get; set; }
}
public class ORMTest
{
public int Id { get; set; }
public string Name { get; set; }
}
实例代码:
using Chloe;
using Chloe.SqlServer;
using System;
using System.Collections.Generic
namespace ConsoleApp1
{
class Program
{
private static string ConnectionString = @"server=DESKTOP-TROTQO7;uid=sa;pwd=123456;database=ChloeTest2";
static void Main(string[] args)
{
var context = GetContext();
#region 插入(Insert)
//Insert可以使用委托,也可不用
//如果传递的是一个函数,即使用含委托的方法,则返回插入成功的数据的实体
//如果传递的是一个实体类,则返回插入成功的数据的id
//var result = context.Insert(() => new User() { Id=Guid.NewGuid().ToString(),Name = "xiaoming2", Age = 20, Gender = Gender.Man, CityId = 1, OpTime = DateTime.Now });
//var result = context.Insert(new User() { Id = Guid.NewGuid().ToString(), Name = "xiaohong", Age = 20, Gender = Gender.Woman, CityId = 1, OpTime = DateTime.Now });
//var result = context.Insert(new City() {Id=1,Name="广州",ProvinceId=1 });//因数据库设置了自动增长,故设置了id=1是没用的
//var result = context.Insert(new Province() { Id = 1, Name = "广东省" });//同上
//批量插入
//var insertList = new List()
//{
// new User() { Id=Guid.NewGuid().ToString(),Name = "小红"+DateTime.Now, Age = 20, Gender = Gender.Man, CityId = 1, OpTime = DateTime.Now },
// new User() { Id=Guid.NewGuid().ToString(),Name = "xiging"+DateTime.Now, Age = 20, Gender = Gender.Man, CityId = 1, OpTime = DateTime.Now },
// new User() { Id=Guid.NewGuid().ToString(),Name = "sdfds"+DateTime.Now, Age = 20, Gender = Gender.Woman, CityId = 1, OpTime = DateTime.Now }
//};
//context.BulkInsert(insertList);//向student表中插入数据,返回插入成功的数据
#endregion
#region 修改(Update)
//var model = context.Query().First();
//model.Name = "被修改的";
//model.OpTime = DateTime.Now;
//var updateResult = context.Update(model); //返回修改成功的条数
#endregion
#region 删除(Delete)
//var deleteResult = context.Delete(a => a.Name == "lu");//删除名字为lu的用户,并返回删除成功的条数
//该框架没有批量删除的功能,故无法演示
#endregion
#region 查询(Select)
//什么是懒加载?懒加载就是只有在tolist()、count()等这些操作才会真正去与数据库进行交互
//IQuery userData = context.Query();//懒加载city表的数据
//var UserModel = userData.Where(a => a.CityId == 1).FirstOrDefault();//查询城市编码为1的数据列表中的第一条数据
//var list = userData.Where(a => a.CityId == 1).ToList();
//var orderList = userData.Where(a => a.CityId> 0).OrderBy(a => a.CityId).ToList();//通过城市编号进行排序
//var topList = userData.Where(a => a.CityId > 0).Take(10).OrderBy(a => a.Age).ToList();//获取前10条数据,并通过年龄排序
//var pageList = userData.Where(a => a.Age > 0).OrderBy(a => a.Age).ThenByDesc(a => a.CityId).Select(a => new { a.Id, a.Name }).Skip(5).Take(10).ToList();//跳过前5条数据,获取后面10条数据
#endregion
#region 多表连接
//三表连接
//var user_city_province = context.Query()
// .InnerJoin((user, city) => user.CityId == city.Id)
// .InnerJoin((user, city, province) => city.ProvinceId == province.Id);
//var joinList = user_city_province.Select((user, city, province) => new { UserId = user.Id,UserName=user.Name, CityName = city.Name, ProvinceName = province.Name }).ToList();
//foreach (var item in joinList)
//{
// Console.WriteLine($"{item.UserId}=>{item.UserName}=>{item.CityName}=>{item.ProvinceName}");
//}
#endregion
#region 分组函数
//var groupList2 = context.Query().GroupBy(a => a.Age).Select(a => new { a.Age, Count = Sql.Count(), Sum = Sql.Sum(a.Age), Max = Sql.Max(a.Age), Min = Sql.Min(a.Age), Avg = Sql.Average(a.Age) }).ToList();
#endregion
#region 事务
//try
//{
// context.Session.BeginTransaction();
// /* do some things here */
// var insertTranList = new List()
// {
// new User() { Id=Guid.NewGuid().ToString(),Name = "小红Tran"+DateTime.Now, Age = 20, Gender = Gender.Man, CityId = 1, OpTime = DateTime.Now },
// new User() { Id=Guid.NewGuid().ToString(),Name = "小刚Tran"+DateTime.Now, Age = 20, Gender = Gender.Man, CityId = 1, OpTime = DateTime.Now },
// new User() { Id=Guid.NewGuid().ToString(),Name = "小明Tran"+DateTime.Now, Age = 20, Gender = Gender.Woman, CityId = 1, OpTime = DateTime.Now }
// };
// context.BulkInsert(insertTranList);//向student表中插入数据,没有返回参数
// //创建一个班级类,并且不映射到数据库中,以此来造成插入抛异常,实现事务的回滚操作
// var cModel = new Classess()
// {
// Id = 1,
// Name = "一年一班"
// };
// context.Insert(cModel);
// context.Session.CommitTransaction();
//}
//catch (Exception ex)
//{
// if (context.Session.IsInTransaction)
// context.Session.RollbackTransaction();
// throw;
//}
#endregion
#region 性能测试
//double sum = 0;
//int count = Convert.ToInt32(ConfigurationManager.AppSettings["circleCount"]);
//for (int i = 1; i <= count; i++)
//{
// Stopwatch watch = new Stopwatch();
// watch.Start();
// var list = context.Query().ToList();
// watch.Stop();
// double useTime = Convert.ToDouble(watch.ElapsedMilliseconds) / 1000;
// sum += useTime;
// Console.WriteLine($"SqlSugar第{i}次查询10万条数据花的时间为:" + useTime + "秒");
//}
//Console.WriteLine($"SqlSugar循环{count}次查询十万条数据的平均耗时为:" + sum / count + "秒");
#endregion
Console.ReadKey();
}
public static MsSqlContext GetContext()
{
MsSqlContext context = new MsSqlContext(ConnectionString);
// context.PagingMode = PagingMode.OFFSET_FETCH;//分页模式
return context;
}
}
}
(1)在nuget中输入Install-Package Dos.ORM或nuget管理工具中搜索Dos.ORM,下载Dos.ORM包
(2)下载代码生成器GitHub:https://github.com/itdos/Dos.Tool
(3)创建相应的数据库,运行步骤2中的代码,通过代码生成器生成实体类的代码
(4)将生成的实体类代码复制到自己创建的项目中(如果不通过官网提供的代码生成器生成代码,而是按照我们平时的做法自己创建的话,查询没问题,但是增删改就都会报错),这里只截图一部分供读者查看,如下图:
(5)简单的实例如下:
相应的实体类(由步骤3中的代码生成器生成):
//------------------------------------------------------------------------------
//
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
// Website: http://ITdos.com/Dos/ORM/Index.html
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
//
//------------------------------------------------------------------------------
using System;
using Dos.ORM;
namespace DOS.ORMTest
{
///
/// 实体类Student。(属性说明自动提取数据库字段的描述信息)
///
[Table("Student")]
[Serializable]
public partial class Student : Entity
{
#region Model
private string _Id;
private string _Name;
private int _Age;
private int _Classess;
private DateTime _CreateTime;
///
///
///
[Field("Id")]
public string Id
{
get { return _Id; }
set
{
this.OnPropertyValueChange("Id");
this._Id = value;
}
}
///
///
///
[Field("Name")]
public string Name
{
get { return _Name; }
set
{
this.OnPropertyValueChange("Name");
this._Name = value;
}
}
///
///
///
[Field("Age")]
public int Age
{
get { return _Age; }
set
{
this.OnPropertyValueChange("Age");
this._Age = value;
}
}
///
///
///
[Field("Classess")]
public int Classess
{
get { return _Classess; }
set
{
this.OnPropertyValueChange("Classess");
this._Classess = value;
}
}
///
///
///
[Field("CreateTime")]
public DateTime CreateTime
{
get { return _CreateTime; }
set
{
this.OnPropertyValueChange("CreateTime");
this._CreateTime = value;
}
}
#endregion
#region Method
///
/// 获取实体中的主键列
///
public override Field[] GetPrimaryKeyFields()
{
return new Field[] {
_.Id,
};
}
///
/// 获取列信息
///
public override Field[] GetFields()
{
return new Field[] {
_.Id,
_.Name,
_.Age,
_.Classess,
_.CreateTime,
};
}
///
/// 获取值信息
///
public override object[] GetValues()
{
return new object[] {
this._Id,
this._Name,
this._Age,
this._Classess,
this._CreateTime,
};
}
///
/// 是否是v1.10.5.6及以上版本实体。
///
///
public override bool V1_10_5_6_Plus()
{
return true;
}
#endregion
#region _Field
///
/// 字段信息
///
public class _
{
///
/// *
///
public readonly static Field All = new Field("*", "Student");
///
///
///
public readonly static Field Id = new Field("Id", "Student", "");
///
///
///
public readonly static Field Name = new Field("Name", "Student", "");
///
///
///
public readonly static Field Age = new Field("Age", "Student", "");
///
///
///
public readonly static Field Classess = new Field("Classess", "Student", "");
///
///
///
public readonly static Field CreateTime = new Field("CreateTime", "Student", "");
}
#endregion
}
}
using Dos.ORM;
using System;
//------------------------------------------------------------------------------
//
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
// Website: http://ITdos.com/Dos/ORM/Index.html
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
//
//------------------------------------------------------------------------------
namespace Dos.ORMTest
{
///
/// 实体类Classes。(属性说明自动提取数据库字段的描述信息)
///
[Table("Classes")]
[Serializable]
public partial class Classes : Entity
{
#region Model
private int _Id;
private string _Name;
private DateTime? _CreateTime;
///
///
///
[Field("Id")]
public int Id
{
get { return _Id; }
set
{
this.OnPropertyValueChange("Id");
this._Id = value;
}
}
///
///
///
[Field("Name")]
public string Name
{
get { return _Name; }
set
{
this.OnPropertyValueChange("Name");
this._Name = value;
}
}
///
///
///
[Field("CreateTime")]
public DateTime? CreateTime
{
get { return _CreateTime; }
set
{
this.OnPropertyValueChange("CreateTime");
this._CreateTime = value;
}
}
#endregion
#region Method
///
/// 获取实体中的主键列
///
public override Field[] GetPrimaryKeyFields()
{
return new Field[] {
_.Id,
};
}
///
/// 获取实体中的标识列
///
public override Field GetIdentityField()
{
return _.Id;
}
///
/// 获取列信息
///
public override Field[] GetFields()
{
return new Field[] {
_.Id,
_.Name,
_.CreateTime,
};
}
///
/// 获取值信息
///
public override object[] GetValues()
{
return new object[] {
this._Id,
this._Name,
this._CreateTime,
};
}
///
/// 是否是v1.10.5.6及以上版本实体。
///
///
public override bool V1_10_5_6_Plus()
{
return true;
}
#endregion
#region _Field
///
/// 字段信息
///
public class _
{
///
/// *
///
public readonly static Field All = new Field("*", "Classes");
///
///
///
public readonly static Field Id = new Field("Id", "Classes", "");
///
///
///
public readonly static Field Name = new Field("Name", "Classes", "");
///
///
///
public readonly static Field CreateTime = new Field("CreateTime", "Classes", "");
}
#endregion
}
}
using Dos.ORM;
using Dos.ORMTest;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
namespace DOS.ORMTest
{
class Program
{
public class DB { public static readonly DbSession Context = new DbSession("connStr"); }//获取访问数据库的上下文
public static void Main(string[] args)
{
#region 查询(Select)
//var list = DB.Context.From()
// .Where(d => d.Age > 0)
// .ToList();
////取部分字段
//var list2 = DB.Context.From()
// .Select(d => new { d.Name, Age = d.Age })
// .ToList();
////分页,获取前十条数据
//var pageList = DB.Context.From()
// .Page(10, 1)
// .OrderBy(m=>m.Age)
// .ToList();
#endregion
#region 新增(Insert)
//var stu = new Student()
//{
// Id = Guid.NewGuid().ToString(),
// Name = "xiaohong",
// Age = 25,
// Classess=1,
// CreateTime = DateTime.Now
//};
//int insertResult2 = DB.Context.Insert(stu);//返回成功条数,也可进行批量插入
////批量插入信息
//var insertList = new List()
//{
// new Student()
// {
// Id = Guid.NewGuid().ToString(),
// Name = "小刚"+DateTime.Now,
// Age = 25,
// Classess=1,
// CreateTime = DateTime.Now
// },
// new Student()
// {
// Id = Guid.NewGuid().ToString(),
// Name = "小明" + DateTime.Now,
// Age = 20,
// Classess=2,
// CreateTime = DateTime.Now
// },
// new Student()
// {
// Id = Guid.NewGuid().ToString(),
// Name = "小红" + DateTime.Now,
// Age = 22,
// Classess=1,
// CreateTime = DateTime.Now
// },
// new Student()
// {
// Id = Guid.NewGuid().ToString(),
// Name = "笑笑" + DateTime.Now,
// Age = 22,
// Classess=2,
// CreateTime = DateTime.Now
// }
//};
////批量插入方法,ORM内部存在事务,不用担心某些数据插入成功,某些数据插入失败。
//var insertResult = DB.Context.Insert(insertList);
#endregion
#region 删除(Delete)
//var model = DB.Context.From().First();
//int deleteResult = DB.Context.Delete(model);//返回成功条数,也可进行批量删除操作
//批量删除
//var deleteList = DB.Context.From().Top(5).ToList();//取前五条数据出来删除
////批量删除方法内部有事务,会自动添加where条件:WHERE id IN(list主键数据)
//var deleteResult = DB.Context.Delete(deleteList);
#endregion
#region 修改(Update)
//var updateModel = DB.Context.From().First();
//updateModel.Name = "赵六";
//int updateResult = DB.Context.Update(updateModel);//返回成功条数,也可进行批量修改操作
//var updateList = DB.Context.From().Top(5).ToList();//取前五条数据出来进行批量修改
//foreach (var item in updateList)
//{
// item.Name = "我是被修改的"+DateTime.Now;
//}
//var updateResult = DB.Context.Update(updateList);//返回成功修改条数
#endregion
#region 分组和多表查询
//多表查询
//var joinList = DB.Context.From()
// .InnerJoin((a, c) => a.Classess == c.Id)//内连接
// .ToDataTable();
////分组
//var groupList = DB.Context.From()
// .GroupBy(m=>m.Classess)//根据班级id分组
// .Select(m=>m.Classess)//分组后的班级id
// .OrderBy(m=>m.Classess)//根据班级id排序
// .Select(m=> new { Name=m.Name,ClassId=m.Classess})
// .ToList();
#endregion
#region 事务
//using (DbTrans trans = DbSession.Default.BeginTransaction())
//{
// try
// {
// var stu = new Student()
// {
// Id = Guid.NewGuid().ToString(),
// Name = "xiaohsdfsdf",
// Age = 25,
// Classess = 1,
// CreateTime = DateTime.Now
// };
// int tranResult = DB.Context.Insert(stu);//向student表中插入数据
// //创建一个测试类,并且不映射到数据库中,以此来造成插入抛异常,实现事务的回滚操作
// var cModel = new ORMTestCls()
// {
// Id = 1,
// Name = "测试"
// };
// int tranResult2 = DB.Context.Insert(stu);//向student表中插入数据
// trans.Commit();
// }
// catch(Exception ex)
// {
// trans.Rollback();
// throw;
// }
//}
#endregion
#region 性能测试
//double sum = 0;
//int count = Convert.ToInt32(ConfigurationManager.AppSettings["circleCount"]);
//for (int i = 1; i <= count; i++)
//{
// Stopwatch watch = new Stopwatch();
// watch.Start();
// var efficeList = DB.Context.From().ToList();
// watch.Stop();
// double useTime = Convert.ToDouble(watch.ElapsedMilliseconds) / 1000;
// sum += useTime;
// Console.WriteLine($"Dos.ORM第{i}次查询10万条数据花的时间为:" + useTime + "秒");
//}
//Console.WriteLine($"Dos.ORM循环{count}次查询十万条数据的平均耗时为:" + sum / count + "秒");
#endregion
Console.ReadKey();
}
}
}
(1)在nuget中输入Install-EntityFramework或nuget管理工具中搜索EntityFramework,下载包
(2)创建一个CodeFirstDBContext.cs文件,并继承DBContext如下图:
相应的实体类:
using System.ComponentModel.DataAnnotations.Schema;
namespace EFCodeFirstTest
{
[Table("Student")]
public class Student
{
///
/// 学生编号 默认自动增长
///
public int Id { get; set; }
///
/// 学生名
///
public string StuName { get; set; }
///
/// 学生年龄
///
public int Age { get; set; }
///
/// 班级编号
///
public int ClassesId { get; set; }
}
}
namespace EFCodeFirstTest
{
[Table("Classes")]
public class Classes
{
///
/// 班级id
///
public int Id { get; set; }
///
/// 班级名
///
public string ClassName { get; set; }
}
}
简单实例如下:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCodeFirstTest
{
class Program
{
static void Main(string[] args)
{
//使用using,可以访问数据库结束后自动关闭数据库连接
using (CodeFirstDbContext db = new CodeFirstDbContext())
{
//db.Database.Delete();//删除数据库
//db.Database.CreateIfNotExists();//如果不存在数据库,那么就创建
#region 新增(Insert)
//Student stu = new Student()
//{
// StuName = "张三",
// Age = 18,
// ClassesId=1
//};
//var insertResult = db.Set().Add(stu);//通过DataSet新增
////var inserResult2 = db.Students.Add(stu);//通过CodeFirstDbContext中定义的DataSet对象新增
////批量插入数据
//var insertList = new List()
//{
// new Student()
// {
// StuName = "批量插入的小明",
// Age = 18,
// ClassesId=1
// },
// new Student()
// {
// StuName = "批量插入的小红",
// Age = 18,
// ClassesId=1
// },
// new Student()
// {
// StuName = "批量插入的王五",
// Age = 18,
// ClassesId=2
// },
// new Student()
// {
// StuName = "批量插入的赵六",
// Age = 18,
// ClassesId=2
// },
// };
//var insertResult3 = db.Set().AddRange(insertList);//返回成功插入的列表
////var inserResult4 = db.Students.AddRange(insertList);
//var classList = new List()
//{
// new Classes{ ClassName="一年一班"},
// new Classes{ ClassName="一年二班"},
// new Classes{ ClassName="二年一班"},
// new Classes{ ClassName="三年一班"},
//};
//var insertResult5 = db.Classess.AddRange(classList);//插入班级表
//db.SaveChanges();//执行操作后必须savechanges一下,不然不会去更新数据库
#endregion
#region 修改(Update)
var updateModel = db.Students.First();//获取第一条数据
updateModel.StuName = "我是单条修改的数据";
//EF中没有update函数,通过修改查询出来的数据,然后saveChanges(),即可执行修改操作
var updateList = db.Students.OrderBy(m=>m.Id).Skip(5).Take(5).ToList();//获取前6-10条数据,必须orderby之后才可以使用skip
foreach (var item in updateList)
{
item.StuName = "被修改的名字" + DateTime.Now;
}
db.SaveChanges();//提交修改,只有执行了当前操作,updateModel、updateList中的数据才会修改
#endregion
#region 查询(Select)
//简单的查询
var selectList = db.Students.Where(m => m.ClassesId == 1).ToList();//查询班级为1的数据
//分页
int pageIndex = 1, pageSize = 10;
var selectList2 = db.Students.OrderBy(m=>m.Id).Skip((pageIndex-1) * pageSize).Take(pageSize).ToList();//获取前十条数据
#endregion
#region 删除(Delete)
var deleteModel = db.Students.First();//获取第一条数据
db.Students.Remove(deleteModel);//删除一条数据
//批量删除
var deleteList = db.Students.OrderBy(m=>m.Id).Skip(5).Take(3).ToList();//获取前6-10条数据
db.Students.RemoveRange(deleteList);
#endregion
#region 分组和子链接(group by and join)
var groupList = db.Students.GroupBy(m => m.ClassesId).Select(m=>m.Count()).ToList();//通过班级id分组,并输出个数
//Join中的参数Join(左连接的表,左表的id,右表的id,输出的匿名类)
var joinList =db.Students.Join(db.Classess, stu => stu.ClassesId,
cls => cls.Id, (stu, cls) => new
{
StuName=stu.StuName,
StuClassName=cls.ClassName
}).ToList();
#endregion
}
#region 事务
//using (var trans = db.Database.BeginTransaction())
//{
// try
// {
// Student stu = new Student()
// {
// StuName = "张三55",
// Age = 18,
// ClassesId = 1
// };
// var transResult = db.Students.Add(stu);//向student表中插入数据
// db.SaveChanges();
// //throw new Exception("抛异常让你回滚");//想要模拟事务回滚,就去掉这段代码的注释
// trans.Commit();
// }
// catch (Exception e)
// {
// trans.Rollback();
// }
//}
#endregion
#region 性能测试
//using (CodeFirstDbContext db = new CodeFirstDbContext())
//{
// // db.Database.CreateIfNotExists();
// double sum = 0;
// int count = Convert.ToInt32(ConfigurationManager.AppSettings["circleCount"]);
// for (int i = 1; i <= count; i++)
// {
// Stopwatch watch = new Stopwatch();
// watch.Start();
// var efficeList = db.Set().ToList();
// watch.Stop();
// double useTime = Convert.ToDouble(watch.ElapsedMilliseconds) / 1000;
// sum += useTime;
// Console.WriteLine($"EFCodeFirst第{i}次查询10万条数据花的时间为:" + useTime + "秒");
// }
// Console.WriteLine($"EFCodeFirst循环{count}次查询十万条数据的平均耗时为:" + sum / count + "秒");
//}
#endregion
Console.ReadKey();
}
}
}
// trans.Commit();
// }
// catch (Exception e)
// {
// trans.Rollback();
// }
//}
#endregion
#region 性能测试
//using (CodeFirstDbContext db = new CodeFirstDbContext())
//{
// // db.Database.CreateIfNotExists();
// double sum = 0;
// int count = Convert.ToInt32(ConfigurationManager.AppSettings["circleCount"]);
// for (int i = 1; i <= count; i++)
// {
// Stopwatch watch = new Stopwatch();
// watch.Start();
// var efficeList = db.Set().ToList();
// watch.Stop();
// double useTime = Convert.ToDouble(watch.ElapsedMilliseconds) / 1000;
// sum += useTime;
// Console.WriteLine($"EFCodeFirst第{i}次查询10万条数据花的时间为:" + useTime + "秒");
// }
// Console.WriteLine($"EFCodeFirst循环{count}次查询十万条数据的平均耗时为:" + sum / count + "秒");
//}
#endregion
Console.ReadKey();
}
}
}