SqlSugar導航查詢/多級查詢

1、導航查詢特點 

作用:主要處理主對象裏面有子對象這種層級關係查詢

1.1 無外鍵開箱就用

其它ORM導航查詢 需要 各種配置或者外鍵,而SqlSugar則開箱就用,無外鍵,只需配置特性和主鍵就能使用

1.2 高性能優 

 查詢 性能非常強悍   5.0.8.1preview02版本進行了性能優化 

 支持大數據分頁導航查詢

3.3 語法超級爽

 var list=db.Queryable<Test>()
           .Includes(t=> t.Provinces, pro=>pro.Citys ,cit=>cit.Street) //多層級
           .Includes(t=> t.ClassInfo)// 一個層級查詢
           .ToList();              
                
 //具體用法看下面文檔介紹
 //多層級可以看2.5

 

2、新導航查詢 

適合有主鍵的常規操作, 請升級到5.0.6.8

2.1 一對一 ( one to one )

//實體
public class StudentA
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int StudentId { getset; }
    public string Name { getset; }
    public  string SexCode { get;set;}
    public int SchoolId { getset; }
     
    //用例1:主鍵模式 StudentA(主表)表中的 SchoolId 和SchoolA(子表)中的主鍵關聯 
    [Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一對一 SchoolId是StudentA類裏面的
    public SchoolA SchoolA { getset; } //不能賦值只能是null
     
    //用例2:反向導航,2個字段匹配關係 
    [Navigate(NavigateType.OneToOne, nameof(SchoolId),nameof(SchoolA.Id))] 
    public SchoolA SchoolA { getset; } //不能賦值只能是null
    //第一個主表字段,第二從表字段  順序不要錯了
     
    //用例3: 字典導航 多了個SQL條件參數  
    //[SqlSugar.Navigate(NavigateType.OneToOne,nameof(SexId),nameof(DataDictionary1.Code),"type='sex'")]
    //具體用法可以看配置查詢 https://www.donet5.com/Home/Doc?typeId=2309
 
}
public class SchoolA
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id{ getset; }
    public string SchoolName { getset; }
 
//導航+主表過濾  導航屬性過濾
var list = db.Queryable<StudentA>()
         .Includes(x => x.SchoolA) //填充子對象 (不填充可以不寫)
         .Where(x =>x.SchoolA.SchoolName=="北大"
         .ToList();
 
 
//導航+主表過濾  只查有導航數據 (新功能:5.1.2.8)
var list = db.Queryable<StudentA>()
         .Includes(x => x.SchoolA) //填充子對象 (不填充可以不寫)
         .Where(x => SqlFunc.Exists(x.SchoolA.主鍵))
         .ToList();            
                          
          
//導航+子表過濾 5.0.9.4-preview06 請注意升級 
//創建一個擴展函數,默認是Class不支持Where
public static List<T> Where<T>(this T thisValue, Func<T,bool> whereExpression ) where T:class,new()
{
   return new List<T>() { thisValue };
var list = db.Queryable<Student_003>()
          .Includes(x => x.school_001.Where(z=>z.Name=="a").ToList())//擴展的Where對子表進行過濾
          .ToList(); //5.0.9.4-preview06 才支持 請注意升級 請注意升級
 
//導航 指定字段 5.1.3.38
var list = db.Queryable<StudentA>()
         .Includes(x => x.SchoolA.ToList(it=>new SchoolA(){ Name =it.Name,id=it.Id})) 
         .ToList();                    
           
           
//導航如果只查一個字段         
var list = db.Queryable<StudentA>()
             .Where(x => x.id>1)  //Where和Select中別名要寫一樣
             .Select(x =>new 
                x=x,
                SchoolName= x.SchoolA.SchoolName
             }).ToList();

多字段1對1 看文檔2.4

2.2 一對多 ( one to many)

BookA(子表)中的studenId和StudentA(主表)中的主鍵關聯

//實體
public class StudentA
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id{ getset; }
    public string Name { getset; }
    public int SchoolId { getset; }
     
    //用例1:正常一對多
    [Navigate(NavigateType.OneToMany, nameof(BookA.studenId))]//BookA表中的studenId
    public List<BookA> Books { getset; }//注意禁止給books手動賦值
     
    //用例2:反向導航支持:StudentA沒有主鍵或者指定關係
    [Navigate(NavigateType.OneToMany, nameof(BookA.studenId),nameof(Id))] 
    public List<BookA> Books { getset; }//注意禁止給books手動賦值
    //與一對一相反 第一個 從表字段,第二個主表字段
 
}
public class BookA
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int BookId { getset; }
    public string Name { getset; }
    public int studenId { getset; }
}
 
//例1:簡單用法
var list = db.Queryable<StudentA>()
.Includes(x => x.Books)
.ToList();
 
//例2:支持Any和Count 對主表進行過濾 (子對象過濾看下面)
var list = db.Queryable<StudentA>()
.Includes(x => x.Books)
.Where(x => x.Books.Any())
//帶條件的
//.Where(x => x.Books.Any(z=>z.Name=="jack")))
.ToList();
 
//例3: 沒有Includes也可以使用過濾
var list2 = db.Queryable<StudentA>()
.Where(x => x.Books.Any())//Any中可以加條件 Any(z=>z.BookId==1)
.ToList();                         
 
 
//例4 Where子對象進行排序和過濾 (支持WhereIF)
var list = db.Queryable<StudentA>()
  .Includes(x => x.Books.Where(y => y.BookId > 0).OrderBy(y => y.BookId).ToList())
  .ToList();
   
//例5 主表+子表都過濾
var list = db.Queryable<StudentA>()
.Includes(x => x.Books.Where(it=>it.Name=="jack"))//只過濾子表
.Where(x => x.Books.Any(z=>z.Name=="jack")))//通過子表過濾主表
.ToList();
   
//例6:Select指定字段
var list= db.Queryable<StudentA>()
           .Includes(x => x.Books.Select(z=>new BookA() { Names = z.Names }).ToList()) 
 
//例7:Select多層級  (結構:StudentAt->books->BookItems)      
var list= db.Queryable<StudentA>()
     .Includes(x => x.Books.Select(z=>new BookA(){Names=z.Name}.ToList(),it=>BookItems)) 
    .ToList();、//Includes中的Select只能是字段 ,不能導航對象           
            
            
//例8:OrderBy指定字段 (Skip Take可以分頁)
var list= db.Queryable<StudentA>()
           .Includes(x => x.Books.OrderBy(z=>z.Id).ToList()) 
           .ToList();
            
//例9:Take取前幾條
var list= db.Queryable<StudentA>()
           .Includes(x => x.Books.Take(10).ToList()) 
           .ToList();          
                       
            
//例10:DTO支持進行了強化   
看標題2.7        
            
            
//例11:一對多後還可用追加字段映射MappingField 如果以前是1個字關聯,現在追加後就成了1+1       
db.Queryable<StudentA>().Includes(x => x.Books.MappingField(z=>z.字段,()=>x.字段).ToList() )
                .ToList();
//MappingField 和 Where區別
//MappingField MappingField用來指定2個對象的關係,Where只能當前表過濾不能和主表進行關聯 
//MappingField 可以多個也可以和Where一起始用

非標準1對多 看文檔2.4

2.3 多對多 ( many to many)

//實體
public class ABMapping1
{
    [SugarColumn(IsPrimaryKey = true)]//中間表可以不是主鍵
    public int AId { getset; }
    [SugarColumn(IsPrimaryKey = true)]//中間表可以不是主鍵
    public int BId { getset; }
}
public class A1
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id { getset; }
    public string Name { getset; }
    [Navigate(typeof(ABMapping1), nameof(ABMapping1.AId), nameof(ABMapping1.BId))]//注意順序
    public List<B1> BList { getset; }//只能是null不能賦默認值
}
public class B1
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id { getset; }
    public string Name { getset; }
    [Navigat(typeof(ABMapping1), nameof(ABMapping1.BId), nameof(ABMapping1.AId))]//注意順序
    public List<A1> AList { getset; }//只能是null不能賦默認值
}  
//例1:簡單用法 直接填充B的集合,只要配置好特性非常簡單
var list3= db.Queryable<A1>().Includes(x => x.BList).ToList(); 
 
 //例2:支持子對象排序和過濾 (支持WhereIF)
var list3= db.Queryable<A1>().Includes(x => x.BList.Where(z=>z.Id>0).ToList()).ToList(); 
 
 //例3:支持主表過濾  Any和Count
var list3= db.Queryable<A1>().Includes(x => x.BList)
                .Where(x=>x.BList.Any())//Any裏面可以加條件 Any(z=>z.xxxx>0)
                .ToList();
 //例4主表+子表都過濾
var list = db.Queryable<StudentA>()
   .Includes(x => x.BList.Where(it=>it.Name=="jack"))//只過濾子表
   .Where(x => x.BList.Any(z=>z.Name=="jack")))//通過子表過濾主表
   .ToList();               
                 
//不使用Includes一樣可以過濾              
var list3= db.Queryable<A1>() 
                .Where(x=>x.BList.Any()) //可以加條件.Where(x=>x.BList.Any(z=>z.xxx==x.yyy))
                .ToList();                
                 
//多對多後還可用追加字段映射MappingField 如果以前是2個字段關聯,現在追加後就成了2+1       
db.Queryable<A1>().Includes(x => x.BList.MappingField(z=>z.字段,()=>x.字段).ToList()  )
                .ToList();
//MappingField 和 Where區別
//MappingField MappingField用來指定2個對象的關係,Where只能當前表過濾不能和主表進行關聯 
//MappingField 可以多個也可以和Where一起始用

2.4  多字段關係映射(可以是N個)

支持多個字段關聯  5.1.4.108-preview32

var list=db.Queryable<UnitAddress011>().Includes(x => x.Persons).ToList();
   
//m是主表字段 c是子表字段 是一個json數組 格式不要錯了 
[Navigate(NavigateType.Dynamic, "[{m:\"Id\",c:\"AddressId\"},{m:\"Id2\",c:\"AddressId2\"}]")]
public List<UnitPerson011> Persons { getset; }

注意:該功能只能用在查詢上,能用正常導航就儘量使用正常導航

2.5 多級導航(例如:省>市>區)

配置好實體類,我們可以多級查詢(一對多、一對多、多對多都支持只要配好類就可以使用)

public class StudentA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int StudentId { getset; }
    public string Name { getset; }
    public int SchoolId { getset; }
    [Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一對一
    public SchoolA SchoolA { getset; }
    [Navigate(NavigateType.OneToMany, nameof(BookA.studenId))]//一對多
    public List<BookA> Books { getset; }//只能是null不能賦默認值
 
}
public class SchoolA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int SchoolId { getset; }
    public string SchoolName { getset; }
    [Navigate(NavigateType.OneToMany, nameof(RoomA.SchoolId))]//一對多
    public List<RoomA> RoomList { getset; }//只能是null不能賦默認值
}
 
public class RoomA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int RoomId { getset; }
    public string RoomName { getset; }
    public int SchoolId { getset; }
}
public class BookA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int BookId { getset; }
 
    public string Name { getset; }
    public int studenId { getset; }
}       
 
var list2 = db.Queryable<StudentA>()
             //查2層
             .Includes(st => st.SchoolA, sch=> sch.RoomList)//查詢2級(等於EF ThenInclude)
             //查1層
             .Includes(st=> st.Books)  
             .ToList()
//說明: 一對多 多對多 一對多 只要配好了都可以多層級使用
  
              
//如果想超過3個層級需要.AsNavQueryable()
//缺點VS提示會消失,直接寫不要在乎意提示不出來,VS關掉在開就行了,只要不改這個代碼提示就不會有問題
db.Queryable<Order>()
    Includes(it=>it.xx)
    .AsNavQueryable()//加這個前面
    .Includes(it=>it.1,it=>it.2,it=>it.3,it=>it.4,it=>it.5..)
//.AsNavQueryable()能不用盡量不要用,正常Includes(+3)重載完全夠用了

 

2.6 性能優化

1、升級 如果搜索不到勾選預覽版本

5.0.8.1 preview02版本針對大數據導航有了很好的性能優化

2、分頁導航

底層分批量查詢 適合一次性查詢1000條以上的導航

    var list = new List<Tree1>();
 
    db.Queryable<Tree1>()
        .Includes(it => it.Child)
        .ForEach(it => list.Add(it), 300); //每次查詢300條

更多用法:https://www.donet5.com/Home/Doc?typeId=2414

3、關聯字段推薦用主鍵,如果非主鍵導航加索引爲佳

2.7 轉DTO (必學的技巧)

1.自動DTO (推薦 )

//Mapster 工具映射 (推薦) 比AutoMapper方便不需要配置
//Nuget直接安裝就行了
 
//簡單示例:結構一樣直接轉換
var list=db.Queryable<StudentA>()
           .Includes(x => x.Books).ToList();
var dtoList=list.Adapt<List<StudentDTO>>()
 
 
//技巧示例:這個用法必學通過規則映射DTO
 public class TreeDTO
 {
      public int Id { getset; }
      public string Name { getset; }
      public int ParentId { getset; }
      public string ParentName { getset; }//對應Parent中的Name
 }
public class Tree
 {
    [SqlSugar.SugarColumn(IsPrimaryKey = true)]
     public int Id { getset; }
     public string Name { getset; }
     public int ParentId { getset; }
     [Navigate(NavigateType.OneToOne,nameof(ParentId))]
     public Tree Parent { getset; } 
}
         
 var list= db.Queryable<Tree>()
                .Includes(it => it.Parent) 
                .ToList();
 //DTO和List不能是同一個類不然這種映射會失效
 var dtolist= list.Adapt<List<TreeDTO>>();//DTO中的ParentName就有值了

2. 手動轉DTO   升級: 5.1.4.71

老版本注意:是Select中用導航對象

//簡單的用法   5.1.4.71
var list = db.Queryable<Student_004>()
        .Includes(x => x.books)
        .Select(x => new Student_004DTO
           {
             books = x.books 
              
            }, true)//true是自動映射其他屬性,匿名對象需要手動
           .ToList();
                  
                 
//Mapster轉換  5.1.4.71
var list = db.Queryable<Student_004>()
        .Includes(x => x.books)
        .Select(x => new Student_004DTO
         {
           name=x.Name,
           books = x.books.Adapt<List<BooksDTO>>() //導航對象用 Mapster轉換 (NUGET安裝)
         })
        .ToList();            
 
//DTO中用方法  5.1.4.71
var list = db.Queryable<Student_004>()
         .Includes(x => x.books)
         .Select(x => new Student_004DTO
                 {
                   name=x.Name, 
                   //導航對象books可以是C#任何方法結尾
                   bookIds=x.books.Select(it=>it.id).ToList(), 
                   booksDto=x.books.Select(it=>new BookDTO()
                                       {  id=it.Id,
                                           Name=it.Name  
                                          }).ToList()
                 })
                .ToList();   
 
//聯表查詢用DTO寫法  5.1.4.71           
var list5= db.Queryable<Student_004>()
           .Includes(x => x.school_001, x => x.rooms)
           .Includes(x => x.books)
           .LeftJoin<Order>((x, y) => x.Id==y.sid)
           .Select((x,y) => new Student_004DTO
           {
               SchoolId = x.SchoolId,
               books = x.books,
               school_001 = x.school_001,
               Name=y.Name
           })
           .ToList();

 

2.8 導航方法

一對多和多對多

在我們一對多和多對多對象我們可以用導航方法Any()和導航方法Count

//注意:不需 Includes 就可以使用
Where(it=>it.導航對象.Any())
Where(it=>it.導航對象.Any(z=>z.id==1))
Where(it=>it..導航對象.Any(List<IConditionalModel>)//5.1 
 
//Count用法類似

一對一函數  5.1.2.9

//注意:不需 Includes 就可以使用
Where(x=>SqlFunc.Exists(x.SchoolA.Id))//查詢存在一對一的主表數據
Where(x=>SqlFunc.Exists(x.SchoolA.Id,List<IConditionalModel>))//查詢存在一對一的主表數據

2.9  Root->books->[A,B]  

如果Books下面有2個導航A和B

//自動寫法,Books下面的A和B都會查詢出來
.IncludesAllSecondLayer(x=>x.Books)  //自動只能有這麼多層次,更深層級需要手動寫法
 
//手動寫法
.Includes(x => x.Books,x=>x.A) 
.Includes(x => x.Books,x=>x.B)

 

2.91 跨庫導航

https://www.donet5.com/Home/Doc?typeId=2244

 

3、支持聯表的導航

 手動映射適合沒有主鍵或者複雜的一些操作,該功能和Includes文檔 2.4比較接近

3.1 創建測試數據

創建類

public class StudentA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int StudentId { getset; }
    public string Name { getset; }
    public int SchoolId { getset; }
    [SugarColumn(IsIgnore = true)]
    public SchoolA SchoolA { getset; }
}
 
public class SchoolA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int SchoolId { getset; }
    public string SchoolName { getset; }
    [SugarColumn(IsIgnore = true)]
    public List<RoomA> RoomList { getset; }
    [SugarColumn(IsIgnore = true)]
    public List<TeacherA> TeacherList { getset; }
}
public class TeacherA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int Id { getset; }
    public int SchoolId { getset; }
    public string Name { getset; }
}
public class RoomA
{
    [SugarColumn(IsPrimaryKey = true)]
    public int RoomId { getset; }
    public string RoomName { getset; }
    public int SchoolId { getset; }
}

創建測試數據

db.CodeFirst.InitTables<StudentA, RoomA, SchoolA,TeacherA>();
db.DbMaintenance.TruncateTable<StudentA>();
db.DbMaintenance.TruncateTable<RoomA>();
db.DbMaintenance.TruncateTable<SchoolA>();
db.DbMaintenance.TruncateTable<TeacherA>();
db.Insertable(new RoomA() { RoomId = 1, RoomName = "北大001室", SchoolId = 1 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 2, RoomName = "北大002室", SchoolId = 1 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 3, RoomName = "北大003室", SchoolId = 1 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 4, RoomName = "清華001廳", SchoolId = 2 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 5, RoomName = "清華002廳", SchoolId = 2 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 6, RoomName = "清華003廳", SchoolId = 2 }).ExecuteCommand();
 
 
db.Insertable(new SchoolA() { SchoolId = 1, SchoolName = "北大" }).ExecuteCommand();
db.Insertable(new SchoolA() { SchoolId = 2, SchoolName = "清華" }).ExecuteCommand();
 
db.Insertable(new StudentA() { StudentId = 1, SchoolId = 1, Name = "北大jack" }).ExecuteCommand();
db.Insertable(new StudentA() { StudentId = 2, SchoolId = 1, Name = "北大tom" }).ExecuteCommand();
db.Insertable(new StudentA() { StudentId = 3, SchoolId = 2, Name = "清華jack" }).ExecuteCommand();
db.Insertable(new StudentA() { StudentId = 4, SchoolId = 2, Name = "清華tom" }).ExecuteCommand();
 
db.Insertable(new TeacherA() {  SchoolId=1, Id=1, Name="北大老師01" }).ExecuteCommand();
db.Insertable(new TeacherA() { SchoolId = 1, Id =2, Name = "北大老師02" }).ExecuteCommand();
 
db.Insertable(new TeacherA() { SchoolId = 2, Id = 3, Name = "清華老師01" }).ExecuteCommand();
db.Insertable(new TeacherA() { SchoolId = 2, Id = 4, Name = "清華老師02" }).ExecuteCommand();

3.2 手動實現二層

注意:普通導航看標題2 ,ThenMapper是用來處理 普通導航不能實現的功能

結構:  Student->SchoolA

var list = db.Queryable<StudentA>().ToList();//這兒也可以聯表查詢
db.ThenMapper(list, stu =>
{
  //如果加Where不能帶有stu參數,stu參數寫到 SetContext
  //可以用Where寫SetContext但是不能帶有stu對象
  stu.SchoolA=db.Queryable<SchoolA>().SetContext(scl=>scl.SchoolId,()=>stu.SchoolId,stu).FirstOrDefault();
   
  //可以聯查詢的
  //stu.xxxx=db.Queryable<SchoolA>().LeftJoin<XXX>().Select(xxxx).SetContext(....).ToList();
});
// SetContext不會生成循環操作,高性能  和直接Where性能是不一樣的

注意:1、如果沒有SetContext那麼這個查詢將會循環

          2、db.ConextId外面和裏面需要是同一個

3.3 聯表導航多層級

注意:普通導航看標題2,ThenMapper是用來處理 普通導航不能實現的功能

瞭解原理後我們用ThenMapper想映射哪層就映射哪層

var treeRoot=db.Queryable<Tree>().Where(it => it.Id == 1).ToList();
//第一層
db.ThenMapper(treeRoot, item =>
{
    item.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => item.Id, item).ToList();
});
//第二層
db.ThenMapper(treeRoot.SelectMany(it=>it.Child), it =>
{
    it.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => it.Id, it).ToList();
});
//第三層
db.ThenMapper(treeRoot.SelectMany(it => it.Child).SelectMany(it=>it.Child), it =>
{
    it.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => it.Id, it).ToList();
});
//這兒只是用樹型結構來證明可以實現無限級別導航查詢 ,實際開發中樹型結構用ToTree實現
public class Tree
{
[SqlSugar.SugarColumn(IsPrimaryKey =true)]
public int Id { getset; }
public string Name { getset; }
public int ParentId { getset; }
[SqlSugar.SugarColumn(IsIgnore = true)]
public Tree Parent { getset; }
[SqlSugar.SugarColumn(IsIgnore = true)]
public List<Tree> Child { getset; }
}
// SetContext不會生成循環操作,高性能  和直接Where性能是不一樣的

新功能 : 請升級到5.0.6.7 預覽版本 及以上 

 

4、樹型查詢

https://www.donet5.com/Home/Doc?typeId=2311

 

5、老版導航查詢

如果使用Mapper的用戶可以看這個

https://www.donet5.com/ask/9/15831

 

6、不加特性使用導航

通過實體AOP方法實現,具體用法看實體配置

EntityService= (type, columnInfo) =>
{
   p.IfTable<Order>().OneToOne(it => it.Item, nameof(Order.ItemId));
}

 

7、自動Include 5.1.4.63

第二層的所有導航自動Include(不支持第三層和第四層)

var list3 = db.Queryable<UnitaStudentA>()
              .IncludesAllFirstLayer().ToList();//有重載可以排除不想要的
               
               //排除說明:
               //IncludesAllFirstLayer(nameof(UnitaStudentA.ProjectPhases)) 
               //這樣就是排除ProjectPhases的導航屬性
               //可以排除多個
               //IncludesAllFirstLayer("a","b") 
               
//自動導航如果有重複的情況: 誰在前面執行哪個
var list3 = db.Queryable<UnitaStudentA>()
              .Includes(it=>it.Order.Where(s=>s.id==1).ToList())
              .IncludesAllFirstLayer().ToList();//自動導航和Order重複
               
//根據名字導航              
db.Queryable<Order>()
//等同於Includes(it=>it.ProjectPhases)
.IncludesByNameString(nameof(Order.ProjectPhases)).ToList()

可以看下圖 自動導航替換了下面註釋代碼  

image.png

注意:

第一層it下面的通過IncludesAllFirstLayer全自動

第二層(it.ProjectTransferDocs)通過IncludesAllSecondLayer半自動。三層四級需要全部手動

 

9、兼容EF CORE 非List<T>的導航

 vra list=db.Queryable<Order>()
               .Includes(it=>it.導航對象.ToList())//通過.ToList()轉成SqlSugar導航類型就行
               .ToList();

 

10、泛型導航

通過鑑別器實現

var dis=db.Queryable<UnitTestDis<Cat>>()
                .Includes(x => x.Animals).ToList();//T是Cat那麼就能導航Cat
                  
var dis2 = db.Queryable<UnitTestDis<Dog>>()
               .Includes(x => x.Animals).ToList();//T是Dog那麼就能導航Dog
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章