LINQ to DB为不同的数据库提供LINQ操作的支持。

LINQ to DB

  • 概括
  • 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。
    • 然后列举了查询、分页和连结的例子。
    • 反正列举了许多例子。

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。
  • 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
            }
        }
        
    • Customize Scaffold with Code
      • 通过生发ScaffoldInterceptors标类来达成。
      • 和T4途径的区别:
        • 装配件可以适配任意.NET语言,但是装配件需要编译
          • 命令行需要指定--customize CustomAssembly.dll
        • T4只支持C#,IDE的支持有限,但是有好多现成的T4模板
          • 命令行需要指定--customize CustomTemplate.t4,任何不以.dll结尾的都会被当作.t4
      • 通过装配件自定义的话,需要
        • 创建一个.NET料库,并引用linq2db.Tools
        • 添加一个标类,从LinqToDB.Scaffold.ScaffoldInterceptors生发
        • 构建出装配件,并在命令行的--custmize选项中使用
      • 通过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)

其他

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)));

参考:

(本篇完)