LINQ to DB为不同的数据库提供LINQ操作的支持。
LINQ to DB
- 概括
- linq2db提供的是从数据库到POCO标例的映射。
- 可以在微型ORM(比如Dapper、Massive或者PetaPoco)之上支持LINQ表达式。
- 比LINQ to SQL或Entity Framework来得轻量。
- 代码示例在https://github.com/linq2db/examples。
- 可以作为LINQPad的driver,代码https://github.com/linq2db/linq2db.LINQPad。
- Let’s get started
- 安装NuGet:
linq2db
。 - 示例采用的是LinqToDB.ProviderName.SqlServer2012。
- 可以从T4模板生成POCO标类。也可以采用Attribute configuration, Fluent configuration或inferring。
- Attribute configuration就是用Attribute把标类成员跟数据库表格对应上。
- Fluent Configuration允许在运行时动态配置映射。可以有多种映射配置。通过MappingSchema来达成。
- Inferred Configuration不使用attribute标注,直接使用标类名和成员名做映射。跟Attribute configuration比起来有一些限制。
- POCO类到数据库的映射要通过DataConnection。
- 然后列举了查询、分页和连结的例子。
- 反正列举了许多例子。
- 安装NuGet:
Articles
- FAQ
- General
- 默认使用
await awaitable.ConfigureAwait(false)
可以通过Configuration.ContinueOnCapturedContext = true;
配置。 - 如果要在连接之后立马做点事,对于Linq To DB 4.0 往上,要使用https://linq2db.github.io/articles/general/interceptors.html。
- 直接在POCO标类之上使用,存在限制
- string默认是nullable的,而int或double则不是,某些情况下会有问题
- 表格和表列名必须匹配标类和成员名
- 默认会将POCO的所有成员写入
- 对于算出的域属,必须将它们标注出来,并忽略掉,如下所示:
public class MyEntity { [Column(SkipOnInsert = true, SkipOnUpdate = true)] public int CalculatedField { get; set; } }
- 文中还指出如何使用SQL Server spatial types。
- 默认使用
- General
- CLI
dotnet tool install -g linq2db.cli
- 这样就可以通过
dotnet-linq2db
,或者dotnet linq2db
来调用之。 -
这种CLI组织方式有点从git。相关.NET文档:https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools
- 常用命令形式:
dotnet linq2db help
dotnet linq2db help scaffold
dotnet linq2db scaffold <options>
dotnet linq2db template [-o template_path]
- 示例
- 连接某目录下的SQLite数据库:
dotnet linq2db scaffold -p SQLite -c "Data Source=c:\Databases\MyDatabase.sqlite"
- 命令行参数也可以用json文件指定:
dotnet linq2db scaffold -i database.json -c "Data Source=c:\Databases\MyDatabase.sqlite
- database.json的内容示例如下:
{ "general": { "provider": "SQLite", "connection": "Data Source=c:\\Databases\\TestDatabase.sqlite", "output": "c:\\MyProject\\DbModel", "overwrite": true } }
- 连接某目录下的SQLite数据库:
- Customize Scaffold with Code
- 通过生发
ScaffoldInterceptors
标类来达成。 - 和T4途径的区别:
- 装配件可以适配任意.NET语言,但是装配件需要编译
- 命令行需要指定
--customize CustomAssembly.dll
- 命令行需要指定
- T4只支持C#,IDE的支持有限,但是有好多现成的T4模板
- 命令行需要指定
--customize CustomTemplate.t4
,任何不以.dll
结尾的都会被当作.t4
- 命令行需要指定
- 装配件可以适配任意.NET语言,但是装配件需要编译
- 通过装配件自定义的话,需要
- 创建一个.NET料库,并引用
linq2db.Tools
- 添加一个标类,从
LinqToDB.Scaffold.ScaffoldInterceptors
生发 - 构建出装配件,并在命令行的
--custmize
选项中使用
- 创建一个.NET料库,并引用
- 通过T4模板自定义的话
- 通过
dotnet linq2db template
创建T4模板 - 编辑Interceptors标类的方法,注入自定义逻辑
- 在命令行的
--custmize
选项中使用
- 通过
- https://linq2db.github.io/articles/CLI.html#interceptors-overview略。
- 通过生发
- SQL
- Joins
- INNER JOIN
- Join operator on single column
join p in db.Product on c.CategoryID equals p.CategoryID
- Using “Where” condition
from p in db.Product.Where(pr => pr.CategoryID == c.CategoryID)
- Using “InnerJoin” function
from p in db.Product.InnerJoin(pr => pr.CategoryID == c.CategoryID)
- Join operator on single column
- INNER JOIN
- Joins
其他
- 支持的数据库列表:https://linq2db.github.io/articles/general/databases.html
- 博客文章:http://blog.linq2db.com/
- https://news.ycombinator.com/item?id=8064682
https://linq2db.github.io/articles/general/interceptors.html
用于在多处扩展Linq2db的执行通道。之前Linq2db采用事件通知来扩展。
新机制提供了下列基础设施:
- 通过一系列拦截器接口,将扩展点合起来
- 提供基础的拦截器标类
- 同一机制可以用于将拦截器注册到IDataContext的实现们(DataConnection, DataContext, RemoteContext)
- 使用LinqToDbConnectionOptions连接配置标例来注册拦截器
Interceptors
拦截器接口:
- IUnwrapDataObjectInterceptor,提供连接裹装器的兼容层,用于MiniProfiler
- IEntityServiceInterceptor,用于实体创建
- IDataContextInterceptor,用于数据上下文服务
- ICommandInterceptor,DbCommand调用拦截器
- IConnectionInterceptor,DbConnection 方法调用拦截器
按上下文划分
RemoteDataContext:
IDataContextInterceptor
IEntityServiceInterceptor
IUnwrapDataObjectInterceptor
DataContext and DataConnection:
ICommandInterceptor
IConnectionInterceptor
IDataContextInterceptor
IEntityServiceInterceptor
IUnwrapDataObjectInterceptor
Interceptors Registration
可以使用多种方式注册:
- 使用既有连接/上下文标例的AddInterceptor 方法
- 在LinqToDbConnectionOptions中添加
- ICommandInterceptor.CommandInitialized支持在上下文的OnNextCommandInitialized 进行单次拦截
SQL
Query Extensions
QueryExtensionScope定义了可以使用扩展的scope。
- None, 对应IQueryable
- TableHint,对应ITable
- TablesInScopeHint,对应IQueryable
- IndexHint,对应ITable
- JoinHint,对应IQueryable
- SubQueryHint,对应IQueryable
- QueryHint,对应IQueryable
其他
SQLite扩展的使用,参考https://github.com/linq2db/linq2db/blob/11406a329f3904e15671348ce52f1a098c927949/Tests/Linq/Linq/FullTextTests.SQLite.cs#L88
var query = db.GetTable<FtsTable>().Where(r => subquery.Select(_ => Sql.Ext.SQLite().RowId(_)).Contains(Sql.Ext.SQLite().RowId(r)));
参考:
(本篇完)