SqlSugar跨庫查詢/多庫查詢

一、跨庫方式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 { getset; }
            public int OrderId { getset; }
            public decimal? Price { getset; }
            [SqlSugar.SugarColumn(IsNullable = true)]
            public DateTime? CreateTime { getset; }
            [Navigate(NavigateType.OneToOne,nameof(OrderId))] //設置關係 對應Order表主鍵
            public Order Order { getset; }
 }
[Tenant("db1")] //實體標爲db1
public class Order
 {
           [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
           public int Id { getset; }
           public string Name { getset; }
           public decimal Price { getset; }
           [SugarColumn(IsNullable = true)]
           public DateTime CreateTime { getset; }
           [SugarColumn(IsNullable = true)]
           public int CustomId { getset; }
           [Navigate(NavigateType.OneToMany, nameof(OrderItem.OrderId))]//
           public List<OrderItem> Items { getset; }
 }
  
//通過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)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章