Loading

导航查询

前言

导航查询特点:

  • 主要处理主对象里面有子对象这种层级关系查询
  • 只需要配置特性和主键即可,不需要外键

1.导航查询用法 (关键字:Includes)

1.1 一对一

用到的实体类:

public class StudentA
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int StudentId { get; set; }
        public string Name { get; set; }
        public int SchoolId { get; set; }
        //新版本修改了命名
        [Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一一 SchoolId是StudentA类里面的
        public SchoolA SchoolA { get; set; } //不能赋值只能是null
    }
    
    
    public class SchoolA
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int SchoolId { get; set; }
        public string SchoolName { get; set; }
    }

代码:

List<StudentA> list = db.Queryable<StudentA>()
                .Includes(it => it.SchoolA)
                .ToList();

string jsonStr1 = JsonConvert.SerializeObject(list);
string Jsonstr2 = db.Utilities.SerializeObject(list);   //sugar提供的序列化方法

//转Json后 将内容粘贴到 https://www.json.cn/ 解析查看数据格式

1.2 一对多

用到的实体类:

public class StudentB
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int StudentId { get; set; }
        public string Name { get; set; }
        public int SchoolId { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(BookB.studenId))]  //BookB表中的studenId
        public List<BookB> Books { get; set; }  //注意禁止给Books手动赋值
    }
    
    
    public class BookB
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int BookId { get; set; }
        public string Name { get; set; }
        public int studenId { get; set; }
    }

1.2.1 简单用法

注意:

  • 简单写法 .Includes(it => it.Books.ToList()) 中的 ToList() 可以省略
List<StudentB> list1 = db.Queryable<StudentB>()
                .Includes(it => it.Books)
                .ToList();

string jsonStr1 = JsonConvert.SerializeObject(list);
string Jsonstr2 = db.Utilities.SerializeObject(list);    //sugar提供的序列化方法

//转Json后 将内容粘贴到 https://www.json.cn/ 解析查看数据格式

1.2.2 对主主对象进行过滤

注意:

  • 支持Any Count,对主对象进行过滤
  • Any 只支持一个层级,第二层级目前不支持
List<StudentB> list = db.Queryable<StudentB>()
                .Includes(it => it.Books)
                .Where(it => it.Name.Equals("B"))
                .ToList();
//提前对主对象进行 条件筛选过滤
List<StudentB> list = db.Queryable<StudentB>()
                .Includes(it => it.Books)
                .Where(it => it.Books.Any(x=>x.Name.Equals("三国")))
                .ToList();

1.2.3 对子对象进行排序和过滤

注意:

  • Includes 中结尾的 ToList() 方法一定不要少了
  • 否则会报错 "need is ToList()"
List<StudentB> list = db.Queryable<StudentB>()
                .Includes(it => it.Books.Where(b => b.BookId > 3).OrderByDescending(b => b.BookId).ToList())
                .ToList();

1.2.4 子表加Select

注意:

  • 子表 studenId 是必有字段,剩下字段看 Select 投影了哪个字段,就会在sql查询中显示哪个字段
var list2 = db.Queryable<StudentB>()
           .Includes(it => it.Books.Select(z => new BookB() { BookId = z.BookId }).ToList())
           .ToList();

// SELECT `BookId` AS `BookId` ,`studenId` FROM `BookB`  WHERE   `studenId` IN (1,2,3,4)
var list2 = db.Queryable<StudentB>()
           .Includes(it => it.Books.Select(z => new BookB() { Name = z.Name }).ToList())
           .ToList();

// SELECT `Name` AS `Name` ,`studenId` FROM `BookB`  WHERE   `studenId` IN(1, 2, 3, 4)

1.2.5 主表加Select

var list = db.Queryable<StudentB>()
                .Includes(x => x.Books.ToList())
                .ToList(it => new
                {
                    AAA = it.StudentId,
                    BBB = it.Name,
                    CCC = it.Books
                });
                
string Jsonstr = db.Utilities.SerializeObject(list);
//转Json后 将内容粘贴到 https://www.json.cn/ 解析查看数据格式

1.3 多对多

用到的实体类:

public class ABMapping1
{
    [SugarColumn(IsPrimaryKey = true)]  //中间表可以不是主键
    public int AId { get; set; }
    [SugarColumn(IsPrimaryKey = true)]  //中间表可以不是主键
    public int BId { get; set; }
}


public class A1
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id { get; set; }
    public string Name { get; set; }
    [Navigate(typeof(ABMapping1), nameof(ABMapping1.AId), nameof(ABMapping1.BId))]  //注意顺序
    public List<B1> BList { get; set; }
}


public class B1
{
    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id { get; set; }
    public string Name { get; set; }
    [Navigat(typeof(ABMapping1), nameof(ABMapping1.BId), nameof(ABMapping1.AId))]   //注意顺序
    public List<A1> AList { get; set; }
}  

1.3.1 简单用法

直接填充子对象B集合,前提是配置好特性

List<A1> list = db.Queryable<A1>()
                .Includes(x => x.BList)
                .ToList();
string Jsonstr = db.Utilities.SerializeObject(list);

1.3.2 子对象的过滤和排序

支持 WhereIF

List<A1> list = db.Queryable<A1>()
                .Includes(it => it.BList.Where(x=>x.Id>3).ToList())
                .ToList();
string Jsonstr = db.Utilities.SerializeObject(list);

1.3.3 主对象过滤

List<A1> list = db.Queryable<A1>()
                .Includes(a1 => a1.BList)
                .Where(a2 => a2.BList.Any(b => b.Id>2))
                .ToList();

string Jsonstr = db.Utilities.SerializeObject(list);

1.4 手动

用到的实体类:

public class StudentC
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int StudentId { get; set; }
        public string Name { get; set; }
        [Navigate(NavigateType.Dynamic, null)] //自定义关系映射
        public List<BookB> Books { get; set; }
    }

代码:

List<StudentC> list = db.Queryable<StudentC>()
                .Includes(it => it.Books.MappingField(z => z.studenId, () => it.StudentId).ToList())
                .ToList();
                
string Jsonstr = db.Utilities.SerializeObject(list);

1.5 多级导航

1.5.1 三层以下的写法

注意:

  • 一对多 多对多 一对多 只要配好了都可以多层级使用

用到的实体类:

public class StudentB
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int StudentId { get; set; }
        public string Name { get; set; }
        public int SchoolId { get; set; }
        [Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一对一
        public SchoolB SchoolB { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(BookB.studenId))]//BookB表中的studenId 一对多
        public List<BookB> Books { get; set; }//注意禁止给Books手动赋值
    }
    
public class SchoolB
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int SchoolId { get; set; }
        public string SchoolName { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(RoomB.SchoolId))]//一对多
        public List<RoomB> RoomList { get; set; }
    }
    
public class RoomB
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int RoomId { get; set; }
        public string RoomName { get; set; }
        public int SchoolId { get; set; }
    }
    
public class BookB
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int BookId { get; set; }
        public string Name { get; set; }
        public int studenId { get; set; }
    }

代码:

var list = db.Queryable<StudentB>()
                .Includes(st => st.Books)//一级
                .Includes(st => st.SchoolB, sch => sch.RoomList)// 一级 + 两级
                .ToList();

string Jsonstr = db.Utilities.SerializeObject(list);

1.5.2 三层以上的写法

注意:

  • 超过3个层级需要.AsNavQueryable()
  • 缺点VS提示会消失,直接写不要在乎意提示不出来,VS关掉在开就行了,只要不改这个代码提示就不会有问题
  • 示例: db.Queryable().AsNavQueryable().Includes(it=>it.1,it=>it.2,it=>it.3,it=>it.4,it=>it.5..)
  • .AsNavQueryable()能不用尽量不要用,正常Includes(+3)重载完全够用了

用到的实体类:

    //省份
    public class Province
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int Pid { get; set; }
        public string Pname { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(City.pid))]
        public List<City> cityList { get; set; }
    }


    //市级
    public class City
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Cid { get; set; }
        public string Cname { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(District.cid))]
        public List<District> districtList { get; set; }
        public int pid { get; set; }
    }


    //区级
    public class District
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Did { get; set; }
        public string Dname { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(Town.did))]
        public List<Town> townList { get; set; }
        public int cid { get; set; }
    }


    //镇
    public class Town
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Tid { get; set; }
        public string Tname { get; set; }
        [Navigate(NavigateType.OneToMany, nameof(Village.tid))]
        public List<Village> villageList { get; set; }
        public int did { get; set; }
    }


    //村
    public class Village
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Vid { get; set; }
        public string Vname { get; set; }
        public int tid { get; set; }
    }

插入数据:

INSERT INTO `province` VALUES (1, '山东省');

INSERT INTO `city` VALUES (1, '烟台市', 1);
INSERT INTO `city` VALUES (2, '青岛市', 1);
INSERT INTO `city` VALUES (3, '威海市', 1);

INSERT INTO `district` VALUES (1, '开发区', 1);
INSERT INTO `district` VALUES (2, '莱山区', 1);
INSERT INTO `district` VALUES (3, '崂山区', 2);

INSERT INTO `town` VALUES (1, '大新店镇', 1);
INSERT INTO `town` VALUES (2, '刘家沟镇', 1);
INSERT INTO `town` VALUES (3, '北沟镇', 1);
INSERT INTO `town` VALUES (4, '解甲庄', 2);

INSERT INTO `village` VALUES (1, '大呼家村', 1);
INSERT INTO `village` VALUES (2, '回家村', 1);
INSERT INTO `village` VALUES (3, '刘家沟村', 2);
INSERT INTO `village` VALUES (4, '安乡刘家村', 2);
INSERT INTO `village` VALUES (5, '北沟一村', 3);
INSERT INTO `village` VALUES (6, '北沟二村', 3);

代码:

//普通查询,三层
 var list1 = db.Queryable<Province>()
                .Includes(p => p.cityList, c => c.districtList, d => d.townList)
                .ToList();
string Jsonstr1 = db.Utilities.SerializeObject(list1);


//三层以上
var list2 = db.Queryable<Province>()
                .AsNavQueryable()
                .Includes(p => p.cityList, c => c.districtList, d => d.townList, t => t.villageList)
                .ToList();

string Jsonstr2 = db.Utilities.SerializeObject(list2);

1.6 大数据导航

暂时没有可测试的环境
文档参考:分批处理

2.内存对象导航 (关键字:SetContext)

  • 手动映射适合没有主键或者复杂的一些操作

用到的实体类:

    public class StudentX
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int StudentId { get; set; }
        public string Name { get; set; }
        public int SchoolId { get; set; }
        [SugarColumn(IsIgnore = true)]
        public SchoolX SchoolX { get; set; }
    }

    public class SchoolX
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int SchoolId { get; set; }
        public string SchoolName { get; set; }
        [SugarColumn(IsIgnore = true)]
        public List<RoomX> RoomList { get; set; }
        [SugarColumn(IsIgnore = true)]
        public List<TeacherX> TeacherList { get; set; }
    }
    
    public class TeacherX
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Id { get; set; }
        public int SchoolId { get; set; }
        public string Name { get; set; }
    }
    
    public class RoomX
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int RoomId { get; set; }
        public string RoomName { get; set; }
        public int SchoolId { get; set; }
    }

插入数据:

            db.Insertable(new RoomX() { RoomId = 1, RoomName = "北大001室", SchoolId = 1 }).ExecuteCommand();

            db.Insertable(new RoomX() { RoomId = 2, RoomName = "北大002室", SchoolId = 1 }).ExecuteCommand();

            db.Insertable(new RoomX() { RoomId = 3, RoomName = "北大003室", SchoolId = 1 }).ExecuteCommand();

            db.Insertable(new RoomX() { RoomId = 4, RoomName = "清华001厅", SchoolId = 2 }).ExecuteCommand();

            db.Insertable(new RoomX() { RoomId = 5, RoomName = "清华002厅", SchoolId = 2 }).ExecuteCommand();

            db.Insertable(new RoomX() { RoomId = 6, RoomName = "清华003厅", SchoolId = 2 }).ExecuteCommand();


            db.Insertable(new SchoolX() { SchoolId = 1, SchoolName = "北大" }).ExecuteCommand();

            db.Insertable(new SchoolX() { SchoolId = 2, SchoolName = "清华" }).ExecuteCommand();


            db.Insertable(new StudentX() { StudentId = 1, SchoolId = 1, Name = "北大jack" }).ExecuteCommand();

            db.Insertable(new StudentX() { StudentId = 2, SchoolId = 1, Name = "北大tom" }).ExecuteCommand();

            db.Insertable(new StudentX() { StudentId = 3, SchoolId = 2, Name = "清华jack" }).ExecuteCommand();

            db.Insertable(new StudentX() { StudentId = 4, SchoolId = 2, Name = "清华tom" }).ExecuteCommand();


            db.Insertable(new TeacherX() { SchoolId = 1, Id = 1, Name = "北大老师01" }).ExecuteCommand();

            db.Insertable(new TeacherX() { SchoolId = 1, Id = 2, Name = "北大老师02" }).ExecuteCommand();

            db.Insertable(new TeacherX() { SchoolId = 2, Id = 3, Name = "清华老师01" }).ExecuteCommand();

            db.Insertable(new TeacherX() { SchoolId = 2, Id = 4, Name = "清华老师02" }).ExecuteCommand();

2.1 实现两层

注意:

  • 结构:StudentX → SchoolX
  • 如果没有SetContext那么这个查询将会循环
  • db.ConextId外面和里面需要是同一个
var list = db.Queryable<StudentX>().Where(it=>it.StudentId==2 || it.StudentId==3).ToList();
            db.ThenMapper(list, stu =>
            {
                stu.SchoolX = db.Queryable<SchoolX>()
                .Where(scl => scl.SchoolId > 1)
                .SetContext(scl => scl.SchoolId, () => stu.SchoolId, stu).FirstOrDefault();
            });

string Jsonstr = db.Utilities.SerializeObject(list);

2.2 实现无线层

用到的实体类:

    //省份
    public class Province
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int Pid { get; set; }
        public string Pname { get; set; }
        [SugarColumn(IsIgnore = true)]
        public List<City> cityList { get; set; }
    }

    //市级
    public class City
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Cid { get; set; }
        public string Cname { get; set; }
        [SugarColumn(IsIgnore = true)]
        public List<District> districtList { get; set; }
        public int pid { get; set; }
    }

    //区级
    public class District
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Did { get; set; }
        public string Dname { get; set; }
        [SugarColumn(IsIgnore = true)]
        public List<Town> townList { get; set; }
        public int cid { get; set; }
    }

    //镇
    public class Town
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Tid { get; set; }
        public string Tname { get; set; }
        [SugarColumn(IsIgnore = true)]
        public List<Village> villageList { get; set; }
        public int did { get; set; }
    }

    //村
    public class Village
    {
        [SugarColumn(IsPrimaryKey = true)]
        public int Vid { get; set; }
        public string Vname { get; set; }
        public int tid { get; set; }
    }

插入数据:

NSERT INTO `province` VALUES (1, '山东省');

INSERT INTO `city` VALUES (1, '烟台市', 1);
INSERT INTO `city` VALUES (2, '青岛市', 1);
INSERT INTO `city` VALUES (3, '威海市', 1);

INSERT INTO `district` VALUES (1, '开发区', 1);
INSERT INTO `district` VALUES (2, '莱山区', 1);
INSERT INTO `district` VALUES (3, '崂山区', 2);

INSERT INTO `town` VALUES (1, '大新店镇', 1);
INSERT INTO `town` VALUES (2, '刘家沟镇', 1);
INSERT INTO `town` VALUES (3, '北沟镇', 1);
INSERT INTO `town` VALUES (4, '解甲庄', 2);

INSERT INTO `village` VALUES (1, '大呼家村', 1);
INSERT INTO `village` VALUES (2, '回家村', 1);
INSERT INTO `village` VALUES (3, '刘家沟村', 2);
INSERT INTO `village` VALUES (4, '安乡刘家村', 2);
INSERT INTO `village` VALUES (5, '北沟一村', 3);
INSERT INTO `village` VALUES (6, '北沟二村', 3);

代码:

var list = db.Queryable<Province>().ToList();
db.ThenMapper(list, pro =>
{
    pro.cityList = db.Queryable<City>().SetContext(c => c.pid, () => pro.Pid, pro).ToList();
});
db.ThenMapper(list.SelectMany(it => it.cityList), city =>
{
    city.districtList = db.Queryable<District>().SetContext(d => d.cid, () => city.Cid, city).ToList();
});
db.ThenMapper(list.SelectMany(it => it.cityList).SelectMany(it => it.districtList), dis =>
{
    dis.townList = db.Queryable<Town>().SetContext(t => t.did, () => dis.Did, dis).ToList();
});
db.ThenMapper(list.SelectMany(it => it.cityList).SelectMany(it => it.districtList).SelectMany(it => it.townList), tow =>
{
    tow.villageList = db.Queryable<Village>().SetContext(v => v.tid, () => tow.Tid, tow).ToList();
});

string Jsonstr = db.Utilities.SerializeObject(list);

文档参考:导航查询

posted @ 2022-08-24 13:47  DotNeter-Hpf  阅读(84)  评论(0编辑  收藏  举报