C# NPOCO 轻量级ORM框架(进阶)
继续翻译NPOCO wiki。
这篇将home上 下面的几个页面翻译。
wiki地址:https://github.com/schotime/NPoco/wiki
上一篇: http://www.cnblogs.com/Aaxuan/p/7366476.html
从数据库映射到现在有对象
使用 SingleInto
、SingleOrDefaultInto
、FirstInto
和 FirstOrDefaultInto
方法,可以将数据库的列映射到现有对象。只有查询中的列将被设置在现有对象上。
public class User
{
public int UserId { get;set; }
public string Email { get;set; }
} var user = new User() { UserId = };
IDatabase db = new Database("connStringName");
db.SingleOrDefaultInto(user, "select Email from users where userid = @0", );
一对多的查询
这帮助您映射一个与嵌套列表对象有一对多关系的查询。鉴于以下类:
public class UserDto
{
public int UserId { get; set; }
public string Name { get; set; }
public List<CarDto> Cars { get; set; }
} public class CarDto
{
public string Make { get; set; }
public string Color { get; set; }
}
查询:
IDatabase db = new Database("connStringName"); //v2
var users = db.FetchOneToMany<UserDto, CarDto>(x => x.UserId,
"select u.*, c.* from Users u inner join Cars c on u.UserId = c.UserId order by u.UserId"); //v3
var users = db.FetchOneToMany<UserDto>(x => x.Cars,
"select u.*, c.* from Users u inner join Cars c on u.UserId = c.UserId order by u.UserId");
这将为您提供一个UserDto对象的列表,并且对于每个对象,也将填充CarDto的列表。
注意:
- 此方法的第一个参数是 lambda 表达式,该表达式标识第一个对象的惟一属性。
- 列的顺序非常重要。它必须与定义的泛型参数的顺序一致。在这个示例中,查询指定了u。然后c * 映射到< UserDto,CarDto >。
- 如果您要映射到用于插入数据的对象,那么你需要确定你对
List<>
使用了[Ignore]
属性。 - 如果您正在使用一个外连接来执行查询,并且您预期其中的一些将不会被填充,请确保在
FetchOneToMany
调用中使用第二个lambda。这将返回许多对象的主要属性。在上面的例子中,这可能是x = > x . carid。 FetchOneToMany
不能用于获取嵌套的一对多关系,也不能用于多个一对多关系。例如,如果UserDto也有一个BoatsDto列表,那么只有CarDto列表或BoatsDto列表可以加载并映射到一个查询。
对嵌套对象映射
这将帮助您将查询映射到有嵌套对象的对象。鉴于以下类:
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
} public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
查询:
IDatabase db = new Database("connStringName");
var users = db.Fetch<User, Address>("select u.UserId, u.Name, u.Street, u.City from Users");
这将给您一个使用嵌套类映射的 user 对象列表。
注意:
- 列的顺序非常重要。查询中的列需要按照指定的泛型参数的顺序指定。如。首先指定用户列,然后指定地址列。
- 如果您要映射到用于插入数据的对象,那么您需要确保使用 [ResultColumn] 属性忽略地址类。从v3中,您还需要添加[ComplexMapping]s属性。
字典和对象数组查询
有时,您不知道查询返回的列。这就是能够映射到字典< string,object >,或object[]的地方。字典和对象数组查询。
var users = db.Fetch<Dictionary<string, object>>("select * from users"); or var users = db.Fetch<object[]>("select * from users");
注意:
从NPoco版本 > 1.0.3 开始,所有数组类型(值类型。string[]、int[]、double[]、DateTime[]等)将是一个有效的通用参数。
跟踪更改的更新
使用快照
快照用于跟踪实体的更改,因此只有更改的属性才会被更新。在下面的示例中,只有新 Name 将被发送到数据库,因为它的年龄值与启动快照时的值相同。
IDatabase db = new Database("connString");
var user = db.SingleById<User>(); // Name = "Ted", Age = 21 var snapshot = db.StartSnapshot(user); // 在此之后的任何更改都将被记录。 user.Name = "Bobby";
user.Age = ; db.Update(user, snapshot.UpdatedColumns()); // 只更新Name列
只有在UpdatedColumns()之前的更改将被包含在变更集中。
复合主键
复合键可以指定通过放置两个逗号之间的列名称 [PrimaryKey]
属性。
[TableName("Users")]
[PrimaryKey("UserId,UserName")]
public class User
{
public int UserId { get; set; }
public string UserName { get;set; }
}
当设置了复合键,AutoIncrement属性总是默认false
。
如果你想使用 SingleById
方法查找一个对象,就可以使用匿名类型。
IDatabase db = new Database("connStringName");
var user = db.SingleById<User>(new {UserId = , UserName = "user"});
多个结果集
该特性使您能够在只调用一次数据库的情况下映射多个查询。
FetchMultiple
方法返回一个 Tuple < T >,List < T1 > >。
IDatabase db = new Database("connStringName");
Tuple<List<User>, List<Address>> data = db.FetchMultiple<User, Address>("select * from users;select * from addresses;");
var users = data.Item1;
var addresses = data.Item2;
支持:
这仅支持可以返回多个结果集的数据库。在IDataReader上实现了NextResult()。通过Npgsql支持Sql Server和Postgresql。
流利的映射
对于一个类的映射,您可以使用 Map < T > 继承,其中 T 是要映射的类。
public class UserMapping : Map<User>
{
public UserMapping()
{
PrimaryKey(x => x.UserId);
TableName("Users");
Columns(x =>
{
x.Column(y => y.Name).Ignore();
x.Column(y => y.Age).WithName("a_ge");
});
}
}
映射也可以从映射继承,并使用For < >方法在一次类中指定所有的映射。
public class OurMappings : Mappings
{
public OurMappings()
{
For<User>().Columns( ....
}
}
数据库工厂设置:
您只需要创建映射一次,我们使用数据库工厂来完成此操作。
public void Application_Start()
{
MyFactory.Setup();
}
public static class MyFactory
{
public static DatabaseFactory DbFactory { get; set; } public static void Setup()
{
var fluentConfig = FluentMappingConfiguration.Configure(new OurMappings());
//或单个的映射
9 //var fluentConfig = FluentMappingConfiguration.Configure(new UserMapping(), ....); DbFactory = DatabaseFactory.Config(x =>
{
x.UsingDatabase(() => new Database("connString"));
x.WithFluentConfig(fluentConfig);
x.WithMapper(new Mapper());
});
}
}
然后你可以在你的代码中使用它。
var database = MyFactory.DbFactory.GetDatabase();
如果你使用的是容器,那么你可以使用类似的东西
For<IDatabase>().Use(() => MyFactory.DbFactory.GetDatabase());
简单LINQ查询
Query<T>
NPoco介绍了一种使用LINQ查询获取对象的简单方法。这里有一个简单的例子。
IDatabase db = new Database("connString");
db.Query<User>().Where(x => x.Name == "Bob")
.OrderBy(x => x.UserId)
.Limit(, )
.ToList();
可用的LINQ关键字:
- ProjectTo
- Count
- Any
- Where
- OrderBy
- OrderByDescending
- ThenBy
- ThenByDescending
- Limit
- Include
- IncludeMany
这里是你如何使用一个IN子句:
var users = db.Query<User>().Where(x => new[] {,,,}.Contains(x.UserId)).ToList();
// 或者使用 'In' 扩展方法
var users = db.Query<User>().Where(x => x.UserId.In(new[] {,,,})).ToList();
在where子句中也可以使用许多字符串方法。这里有几个例子:
var users = db.Query<User>().Where(x => x.Name.StartsWith("Bo")).ToList();
var users = db.Query<User>().Where(x => x.Name.EndsWith("ob")).ToList();
var users = db.Query<User>().Where(x => x.Name.Contains("o")).ToList();
var users = db.Query<User>().Where(x => x.Name.ToLower() == "bob").ToList();
var users = db.Query<User>().Where(x => x.Name.ToUpper() == "BOB").ToList();
注意:并不是所有的操作都已经实现了。
查询提供
Query<T>
查找用户id大于50的所有用户,按名称排序,只返回20个记录。
var users = db.Query<User>()
.Where(x => x.UserId > )
.OrderBy(x => x.Name)
.Limit(, )
.ToList();
注意:
查询将只在ToList()、ToEnumerable()或返回1值的标量方法中运行。
UpdateMany<T>
在必要的情况下,使用 Where 更新所有类型T 。
var list = new[] {, , , };
// 只更新模板传递的(1、2、3、4)中 UserId 对象的 Name字段
// 如果使用 ExecuteDefaults 方法,则不会设置默认属性 null,或为0的int
db.UpdateMany<User>()
.Where( x => x.UserId.In(list))
//.ExcludeDefaults()
.OnlyFields(x => x.Name)
.Execute(new User() {Name = "test"});
注意:
查询只在执行调用时运行。
DeleteMany<T>
在必要的情况下,使用 Where 删除所有类型T 。
var list = new[] {, , , }; db.DeleteMany<User>()
.Where(x => list.Contains(x.UserId))
.Execute();
注意:
查询只在执行调用时运行。
版本列支持
[VersionColumn]
一个数字字段可以用来检测相互冲突的更新:
[TableName("Users")]
[PrimaryKey("UserId")]
public class User
{
public int UserId { get;set; } [VersionColumn("VersionInt", VersionColumnType.Number)]
public long VersionInt { get; set; }
}
更新将自动检查和增加版本,如果它已经过时,就会抛出 DBConcurrencyException 异常。
这可以通过设置来禁用:VersionException = VersionExceptionHandling.Ignore。
在SQL Server中,rowversion timestamp 数据类型
可用于与VersionColumnType.RowVersion版本列:
[TableName("Users")]
[PrimaryKey("UserId")]
public class User
{
public int UserId { get;set; } [VersionColumn("Version", VersionColumnType.RowVersion)]
public byte[] Version { get; set; }
}
Sql模板
您可以使用SqlBuilder在有条件的地方建立查询,例如,列,orderby等。
var sqlBuilder = new SqlBuilder();
var template = sqlBuilder.AddTemplate("select * from users where age > @0 and /**where**/", );
这里你可以指定一个 Where、Select、Join、LeftJoin、OrderBy、OrderByCols、GroupBy 和 Having 相应的sql令牌在下面指定。
/// Adds a filter. The Where keyword still needs to be specified. Uses /**where**/
public SqlBuilder Where(string sql, params object[] parameters) /// Replaces the Select columns. Uses /**select**/
public SqlBuilder Select(params string[] columns) /// Adds an Inner Join. Uses /**join**/
public SqlBuilder Join(string sql, params object[] parameters) /// Adds a Left Join. Uses /**leftjoin**/
public SqlBuilder LeftJoin(string sql, params object[] parameters) /// Adds an Order By clause. Uses /**orderby**/
public SqlBuilder OrderBy(string sql, params object[] parameters) /// Adds columns in the Order By clause. Uses /**orderbycols**/
public SqlBuilder OrderByCols(params string[] columns) /// Adds a Group By clause. Uses /**groupby**/
public SqlBuilder GroupBy(string sql, params object[] parameters) /// Adds a Having clause. Uses /**having**/
public SqlBuilder Having(string sql, params object[] parameters)
语句可以被链接,并且每个新语句的参数从0开始。
sqlBuilder
.Where("height >= @0", )
.Where("weight > @0 and weight < @1", , ); var db = new Database("conn");
db.Fetch<User>(template);
可以在任何可以使用Sql类的地方使用模板。
到此为止,wiki 主页上的文章除了一篇讲调试的,还有右侧列表中有二,三篇没有翻译。
翻译过程中挺难受的,英语看的一知半解,代码也一知半解,经常看完代码才明白英文意思。。
不过还好是翻译的意思都差不多,可能会有理解,翻译错误的地方,有发现的园友还请指出,以便改正。
翻译时间 2017/8/20
C# NPOCO 轻量级ORM框架(进阶)的更多相关文章
- C# NPOCO 轻量级ORM框架(入门)
目前公司使用这个框架,搜不到很详细的中文资料. 只有英文wiki,所以翻译学习一下. 因为博主也是低水平的,可能会有一些理解不到位的地方. 可能会有错误的地方,如果有园友发现可以指出. wiki地址: ...
- 轻量级ORM框架初探-Dapper与PetaPoco的基本使用
一.EntityFramework EF是传统的ORM框架,也是一个比较重量级的ORM框架.这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择. 1.1 准备一张数据库 ...
- c# 轻量级ORM框架 实现(一)
发布一个自己写的一个轻量级ORM框架,本框架设计期初基于三层架构.所以从命名上来看,了解三层的朋友会很好理解. 设计该框架的目的:不想重复的写增删改查,把精力放到功能实现上. 发布改框架的原因:希望给 ...
- 轻量级ORM框架 QX_Frame.Bantina(二、框架使用方式介绍)
轻量级ORM框架QX_Frame.Bantina系列讲解(开源) 一.框架简介 http://www.cnblogs.com/qixiaoyizhan/p/7417467.html 二.框架使用方式介 ...
- 轻量级ORM框架 QX_Frame.Bantina(一、框架简介)
轻量级ORM框架QX_Frame.Bantina系列讲解(开源) 一.框架简介 http://www.cnblogs.com/qixiaoyizhan/p/7417467.html 二.框架使用方式介 ...
- .NET轻量级ORM框架Dapper入门精通
一.课程介绍 本次分享课程包含两个部分<.NET轻量级ORM框架Dapper修炼手册>和<.NET轻量级ORM框架Dapper葵花宝典>,阿笨将带领大家一起领略轻量级ORM框架 ...
- 轻量级ORM框架Dapper应用一:Dapper安装
一.Dapper简介 Dapper是一款轻量级ORM框架,为解决网站访问流量极高而产生的性能问题而构造,主要通过执行TSQL表达式而实现数据库的CQRS. 如果你在项目中遇到性能访问问题,选择Dapp ...
- 分享自己写的基于Dapper的轻量级ORM框架~
1.说明 本项目是一个使用.NET Standard 2.0开发的,基于 Dapper 的轻量级 ORM 框架,包含基本的CRUD以及根据表达式进行一些操作的方法,目前只针对单表,不包含多表连接操作. ...
- C# 性能优化 之 秒表 Stopwatch。 Dapper一个和petapoco差不多的轻量级ORM框架
Sweet小马 小马同学的编程日记. C# 性能优化 之 秒表 Stopwatch. 生词解释:Diagnostics[,daɪəg'nɑstɪks] n.诊断学 using System.Diagn ...
随机推荐
- Django认证系统实现的web页面
结合数据库.ajax.js.Djangoform表单和认证系统的web页面 一:数据模块 扩展了Django中的user表,增加了自定义的字段 from django.db import models ...
- rsync同步文件(多台机器同步代码...)
常用组合 rsync -av --delete-after --exclude-from="a.txt" x/x -e ssh x:/x/x a.txt 制定忽略的文件, ...
- CSS 特殊性、继承与层叠
一.特殊性规则 选择器的特殊性由选择器本身的组件确定:特殊性由四个部分组成,其初始值为0,0,0,0. 1. 对于选择器中的每一个id,记0,1,0,0: 2. 对于选择器中的每一个类.伪 ...
- 自然语言处理词向量模型-word2vec
自然语言处理与深度学习: 语言模型: N-gram模型: N-Gram模型:在自然语言里有一个模型叫做n-gram,表示文字或语言中的n个连续的单词组成序列.在进行自然语言分析时,使用n-gram或者 ...
- 【比赛游记】THUSC2018酱油记
day -1 早上4:30就要起来去飞机场…… 7点的飞机,10:30就到北京了. 北京的街景并没有我想像的漂亮……大概是因为我在四环外〒▽〒 晚上还有CF div3场,果断的去水了,因为太累就没有打 ...
- socket相关系统调用的调用流程
最近一直在读内核网络协议栈源码,这里以ipv4/tcp为例对socket相关系统调用的流程做一个简要整理,这些相关系统调用的内部细节虽然各有不同,但其调用流程则基本一致: 调用流程: (1)系统调用 ...
- Linux下C程序的反汇编【转】
转自:http://blog.csdn.net/u011192270/article/details/50224267 前言:本文主要介绍几种反汇编的方法. gcc gcc的完整编译过程大致为:预处理 ...
- 如何调整Linux内核启动中的驱动初始化顺序-驱动加载优先级
Linux内核为不同驱动的加载顺序对应不同的优先级,定义了一些宏: include\linux\init.h #define pure_initcall(fn) __define_initcall(& ...
- 数据库-mysql函数
一:MySQL中提供了许多内置函数 CHAR_LENGTH(str) 返回值为字符串str 的长度,长度的单位为字符.一个多字节字符算作一个单字符. 对于一个包含五个二字节字符集, LENGTH()返 ...
- 洛谷P2812校园网络
传送门啦 其实这个题只要读懂分析好题意就不是很难. 就是将一个有向图进行缩点操作,把一个强连通分量看成一个点,求入度为 0 的点和出度为 0 的点各有多少. 在这里先向大家推荐两个题目,建议大家先去看 ...