一、跨庫方式1:跨庫導航 (5.1.3.24)
優點1:支持跨服務器,支持跨數據庫品種, 支持任何類型數據庫
優點2: 超級強大的性能,能達到本庫聯表性能
缺點:不支持子表過濾主表 (方案有ToList後在內存過濾, 如果分頁可以查前1000條主表在內存分頁 前端只顯示前10頁)
[Tenant( "db2" )] //實體標爲db2 public class OrderItem { [SqlSugar.SugarColumn(IsPrimaryKey = true , IsIdentity = true )] public int ItemId { get ; set ; } public int OrderId { get ; set ; } public decimal ? Price { get ; set ; } [SqlSugar.SugarColumn(IsNullable = true )] public DateTime? CreateTime { get ; set ; } [Navigate(NavigateType.OneToOne,nameof(OrderId))] //設置關係 對應Order表主鍵 public Order Order { get ; set ; } } [Tenant( "db1" )] //實體標爲db1 public class Order { [SugarColumn(IsPrimaryKey = true , IsIdentity = true )] public int Id { get ; set ; } public string Name { get ; set ; } public decimal Price { get ; set ; } [SugarColumn(IsNullable = true )] public DateTime CreateTime { get ; set ; } [SugarColumn(IsNullable = true )] public int CustomId { get ; set ; } [Navigate(NavigateType.OneToMany, nameof(OrderItem.OrderId))] // public List<OrderItem> Items { get ; set ; } } //通過ConfigId進行區分是哪個庫 var db = new SqlSugarClient( new List<ConnectionConfig>() { new ConnectionConfig(){ConfigId= "db1" ,DbType=DbType.Sqlite, ConnectionString= "DataSource=/Db_OrderDb.sqlite" ,IsAutoCloseConnection= true }, new ConnectionConfig(){ConfigId= "db2" ,DbType=DbType.Sqlite, ConnectionString= "DataSource=/Db_OrderItemDb.sqlite" ,IsAutoCloseConnection= true } }); //注意:如果是接口需要 //db.AsTenant().QueryableWithAttr<OrderItem>() //通過實體類特性Tenant自動映射不同數據庫進行查詢 var list=db.QueryableWithAttr<OrderItem>() .Includes(z => z.Order) .ToList(); //1行代碼就搞定了2個庫聯表查詢 //不通過特性實現跨庫導航 var list =db.GetConnection( "db1" ).Queryable<OrderItem>() //Orderitem是db1 .CrossQuery( typeof (Order), "db2" ) //Order是db2 .Includes(z => z.Order) .ToList(); |
詳細教程 (5.1.3.25):
https://www.cnblogs.com/sunkaixuan/p/16767798.html
二、手動跨庫查詢
優點:聯表語法100%可以用
缺點:只支持個別數據庫,並且跨服務器比較麻煩需要配置dblink
大多數的數據庫支持下面的寫法,我們可以通過As指定是哪個庫, 查詢的時候用別名
注意:不同數據庫寫法有區別 下面是SqlServer例子 : 庫名.dbo.表名
//單表跨庫 var list=db.Queryable<Order>().AS( "xx.dbo.Order2019" ).ToList(); //SqlServer (跨庫用dblink) var list1 = db.Queryable<Order>() //主表用當前db就行了 .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId, "yy.dbo.OrderItem" ) .LeftJoin<Custom>((o, i, c) => c.Id == o.CustomId, "zz.dbo.Custom" ) .Where((o,i,c)=> o.TypeId==1) .Select((o,i,c)=> new classA() { oid=o.Id , iname=i.Name }) .ToList(); //MySql (只能同服務器) var list1 = db.Queryable<Order>(). //如果跨服務器需要配置dblink,語法上每種數據庫有點小差異 .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId, "yy.OrderItem" ) .LeftJoin<Custom>((o, i, c) => c.Id == o.CustomId, "zz.Custom" ) .Where((o,i,c)=> o.TypeId==1) .Select((o,i,c)=> new classA() { oid=o.Id , iname=i.Name }) .ToList(); //Oracle var list1 = db.Queryable<Order>() .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId, "\"ORDERITEM\"@dblink_name" ) .LeftJoin<Custom>((o, i, c) => c.Id == o.CustomId, "\"CUSTEM\"@dblink_name" ) .Where((o,i,c)=> o.TypeId==1) .Select((o,i,c)=> new classA() { oid=o.Id , iname=i.Name }) .ToList(); //其他庫同理 //老版本:多表跨庫 var list1 = db.Queryable<Order>().AS( "xx.dbo.order" ) // AS("") .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId).AS<OrderItem>( "yy.dbo.OrderItem" ) //AS<T> .LeftJoin<Custom>((o, i, c) => c.Id == o.CustomId) .AS<Custom>( "zz.dbo.Custom" ) //AS<T> .Select((o,i,c)=> new classA() { oid=o.Id , iname=i.Name }) .ToList(); //獲取表名可以減少字符串操作 var tableName=db.EntityMaintenance.GetTableName<T>() //如果有2個AS<T>是相同我們可以這麼寫 .LeftJoin(db.Queryable<T>().AS( "xx.dbo.zzzz" ),(o,i)=>o.id==i.id) |
請升級到5.1.4.86-preview01+
三、同服務器:自動查詢跨庫查詢
3.1 Mysql和SqlServer自動
注意:
1.只支持MySql和SqlServer同服務器並且是同一種類型的庫(你有辦法支持其他庫可以反饋給我)
2.查詢用的是QueryableWithAttr不是Queryable
//聲名SqlSugar對象 var db = new SqlSugarClient( new List<ConnectionConfig>() { new ConnectionConfig(){ConfigId= "A" ,DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection= true }, new ConnectionConfig(){ConfigId= "B" ,DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection= true }, new ConnectionConfig(){ConfigId= "C" ,DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection= true } }); //實體配置是哪個庫 [Tenant( "A" )] //實體標爲A表示是A庫 public class OrderItem [Tenant( "B" )] //實體標爲B表示是B庫 public class Order //聯表查詢要5.1.4.66+才支持 var list = db.QueryableWithAttr<Order>() //根根據ConfigId自動實現跨庫 .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId) .LeftJoin<Custom>((o, i, c) => c.Id == o.CustomId) .Where((o,i,c)=> o.TypeId==1) .Select((o,i,c)=> new classA() { oid=o.Id , iname=i.Name }) .ToList(); //ISqlSugarClient需要轉一下租戶接口,才能用租戶方法 var list =db.AsTenant().QueryableWithAttr<Order>().... |
3.2 自動: PgSql跨Scheme查詢
var db = new SqlSugarClient( new List<ConnectionConfig>() { new ConnectionConfig(){ConfigId= "A" ,DbType=DbType.PostgreSQL, ConnectionString= ".." ,IsAutoCloseConnection= true }, new ConnectionConfig(){ConfigId= "B" ,DbType=DbType.PostgreSQL, DbLinkName= "public" , //重點 ConnectionString= ".....;searchpath=public" //重點 ,IsAutoCloseConnection= true }, }); var x3 = db.QueryableWithAttr<OptRole>() .LeftJoin<Role>((x1, y1) => x1.roleId == y1.id) //Left Join時會加上public. .ToList(); //ISqlSugarClient需要轉一下租戶接口,才能用租戶方法 var list =db.AsTenant().QueryableWithAttr<Order>().... |
3.3 其他庫同服務器
找庫規則3種:
1.SqlServer: 庫名.dbo.表名
2.PgSql或者同類庫:有配置 DbLinkName和 searchpath : DbLinkName.表名
3.其他庫: 庫名.表名
用法就上面3種用法,如果發現哪個數據庫不支持可以和我反饋
四、跨服務器:自動跨庫查詢
除了sqlite,其他的應該都支持dblink配置,只要能配置dblink就能跨庫查詢,也支持同服務器跨庫
4.1 配置SqlServer dblink
請升級5.1.4.72-preview02+
var db = new SqlSugarClient( new List<ConnectionConfig>() { new ConnectionConfig(){ConfigId= "A" ,DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection= true }, new ConnectionConfig(){ ConfigId= "B" , DbType=DbType.SqlServer, DbLinkName= "db1.ecology2013_SHQC2.dbo" , //配置跨庫可以用的表名 ConnectionString= ".." ,IsAutoCloseConnection= true } }); //實體配置是哪個庫 [Tenant( "B" )] //實體標爲A表示是A庫 public class OrderItem //聯表查詢要5.1.4.66+才支持 var list1 = db.QueryableWithAttr<Order>() //根根據ConfigId自動實現跨庫 .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId) .ToList(); //生成Sql //Left join db1.ecology2013_SHQC2.dbo.OrderItem |
下面是SqlServer的例子
可以企業管理器裏添加linkserver實現。
使用sp_addlinkedserver創建一個鏈接的服務器,使其允許對分佈式的、針對 OLEDB 數據源的異類查詢進行訪問。
在使用 sp_addlinkedserver 創建鏈接的服務器之後,此服務器就可以執行分佈式查詢。
步驟:
1. 創建linkserver
EXEC sp_addlinkedserver
@server='DB1',--被訪問的服務器別名
@srvproduct='', --sqlserver不需要指定
@provider='SQLOLEDB',
5@datasrc='192.168.1.102' --要訪問的服務器
2. 登錄鏈接服務器
EXEC sp_addlinkedsrvlogin
'DB1', --被訪問的服務器別名
'false', --useself
NULL, --locallogin
'sa', --帳號
'123456' --密碼
4.2 配置 Oracle dblink
請升級到5.1.4.86-preview02+
var db = new SqlSugarClient( new List<ConnectionConfig>() { new ConnectionConfig(){ConfigId= "A" ,DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection= true }, new ConnectionConfig(){ ConfigId= "B" , DbType=DbType.SqlServer, DbLinkName= "@dblink_name" , //配置dblink名字要@開頭 ConnectionString=..,IsAutoCloseConnection= true } }); //實體配置是哪個庫 [Tenant( "B" )] //實體標爲A表示是A庫 public class OrderItem //聯表查詢要5.1.4.66+才支持 var list1 = db.QueryableWithAttr<Order>() //根根據ConfigId自動實現跨庫 .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId) .ToList(); //生成Sql //Left join OrderItem@dblink_name |
下面是Oracle的例子
CREATE DATABASE LINK dblink_name CONNECT TO target_username IDENTIFIED BY target_passwordUSING '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=target_host) (PORT=target_port))(CONNECT_DATA=(SERVICE_NAME=target_service_name)))'; |
4.3 配置 PgSql Pwd外部表
請升級到5.1.4.86-preview02+
var db = new SqlSugarClient( new List<ConnectionConfig>() { new ConnectionConfig(){ConfigId= "A" ,DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection= true }, new ConnectionConfig(){ ConfigId= "B" , DbType=DbType.SqlServer, DbLinkName= "remote_" , //命名要以_結尾 ConnectionString=..,IsAutoCloseConnection= true } }); //實體配置是哪個庫 [Tenant( "B" )] //實體標爲A表示是A庫 public class OrderItem //聯表查詢要5.1.4.66+才支持 var list1 = db.QueryableWithAttr<Order>() //根根據ConfigId自動實現跨庫 .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId) .ToList(); //生成Sql //Left join remote_OrderItem |
下面是PgSql的例子
首先,在源數據庫中創建 postgres_fdw 擴展:
CREATE EXTENSION postgres_fdw; |
在源數據庫中創建外部服務器對象,指定目標數據庫的連接信息:
CREATE SERVER target_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (dbname 'targetdb' , host 'targethost' , port 'targetport' ); |
在上面的示例中,target_server 是外部服務器的名稱,你需要提供目標數據庫的連接信息,如目標數據庫的名稱、主機和端口。
創建用戶映射,將源數據庫的用戶映射到目標服務器的用戶:
CREATE USER MAPPING FOR current_user SERVER target_server OPTIONS (user 'targetuser' , password 'targetpassword' ); |
確保提供正確的目標服務器的用戶名和密碼。
創建外部表,在源數據庫中創建一個外部表,該表將映射到目標數據庫中的表:
CREATE FOREIGN TABLE IF NOT EXISTS remote_OrderItem ( column1 INT, column2 TEXT, ... ) SERVER target_server; |
字段結構要一樣才能同步
現在,你可以在源數據庫中查詢外部表,就像查詢本地表一樣:
SELECT * FROM remote_table; |
請升級到5.1.4.86-preview02+
4.4 其他跨服務器聯表
只要配置好dblinkName找表規則:
1.默認: dblinkName.[表名]
2.dblinkName以_結尾: dblinkName表名 (這個表名是沒有轉釋符號的,像`` 、[]、 "" 我們稱爲轉釋符號)
3.dblinkName以@開頭: [表名]@dblinkName
var list1 = db.QueryableWithAttr<Order>() //根根據ConfigId自動實現跨庫 .LeftJoin<OrderItem>((o,i)=> o.Id == i.OrderId) .ToList(); //生成Sql //Left join 規則生成的表名 |
請升級到5.1.4.86-preview02+
五、跨庫子查詢
5.1 用ThenMapper實現
支持跨庫的類型,只能用在Select對象填充
//跨庫 var mydb=db.GetConnection(1); mydb.ThenMapper(root,item=>{...}); |
5.2 Subqueryable
請升級:5.1.4.107-preview11+
db.Queryable<Order>() .Select(it => new { x= SqlFunc.Subqueryable<OrderItem>().AsWithAttr().Select(s => s.OrderId) //生成表名規則看:4.4和3.3 }) .ToList(); //也可以用AS("表名") SqlFunc.Subqueryable<Order>().AS( "yyy.Order01" ) .InnerJoin<OrderItem>((x,y)=>x.Id==y.OrderId, "yyy.OrderItem01" ) .Select(x=>x.Id) |