C# 使用Linq递归查询数据库遇到的问题及解决方法

简介:

User表通常是我们在写“XX管理系统”项目时必须要用到的,有的情况下人员的分类属于树形结构,就是除了最高层和最低层,中间层都有相对的父和子,设计数据库的时候,我们通常会加一个parent_id这样的字段。这样我们就可以通过当前用户的user_id查询出他的直接下属有哪些,或者通过parent_id查询出他的直接上司是谁。

但是当我们想通过user_id去查询出其所有下属的时候,就不是能用一条简单的sql能实现的了。如果项目要是.Net Framework3.5以下的,就是没有Linq的时候,通常会在数据库里写一个函数,然后在写sql的时候直接调用函数就能得到一个筛选出来的结果集。如果是Linq呢?我想应该就是要写一个静态方法了,正好自己遇到了一个这样的问题,也是刚接触Linq,所以试着写了一下。

不过无论是在数据库中写函数还是在项目中写一个静态方法,我想都是要用到递归去实现的。

我的思路就是传入当前的user_id然后返回它的所有下属的结果集。最后在这个结果集上去根据条件查询。但是,在写这个方法的过程中还是遇到了几个问题:

1、如何将查询出来的结果集var类型,转换成List<T>类型

最开始我是这样去写的

1
2
3
4
/*大错特错*/
var  list =  from  .......  where ....  select ...;
.....
return  list.ToList<T>();

现在看看我还是挺有创造力的哈,居然能写出这么个东西。

首先不说list.ToList<T>();本身就画红线,为什么我要在最后 return 的时候才去ToList()呢?原因是我知道var 可以用“+=”运算符。这样递归的时候将深一层的返回值直接+到一起,用起来方便一些。

啊~真是大错特错了,首先,按照我的思路,深一层返回的值已经是ToList类型了,所以不能再用+=运算符了.其次,好吧,我承认,我还是没有太了解var是个什么东西。其实在程序运行之后,list就会有一个明确的类型,是系统去自动判定出来的。var只是使我们编程的时候更方便一些,有点像程序蜜糖(忘记是从哪听来的了),也就是说系统应该能识别出list是一个T类型对象的集合,而我这么写就有点画蛇添足的意味了。

正解:

1
2
3
var  list = ( from  .......  where ....  select ...).ToList();
.....
return  list;

这样,list 就会变成我想要的List<T>类型了,因为函数的返回值就是这个类型,所以正是我想要的。

2、提示报错:Collection was modified; enumeration operation may not execute.

这个错误的原因是因为用foreach遍历的时候,对Collection(这里的temp)这个数据集进行了Add/Remove操作。这样就有可能在未遍历到最后的时候,就把这个Collection给修改了,随之就报错了。解决办法有说用for代替foreach的,但是我还是觉得foreach要好些,所以创建了一个Collection这个结果集副本,然后一个用作遍历,一个用作Add/Remove操作,当然,返回的是用后者。

注意创建副本的时候一定新new一个对象,而不是直接声明之后赋值,否则跟没写一样。

1
2
3
List<T> tmpList = list;  //错误
 
List<T> tmpList =  new  List<T>(list); //正确

最后完整的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
         contextdata ctdt =  new  contextdata();        
         public  static  List<db_userinfo> findallchildren( int  parentid)
         {
             var  list = ( from  in  ctdt.db_userinfo                        
                         where  c.parent_id == parentid
                         select  c).ToList();
             List<db_userinfo> tmpList =  new  List<db_userinfo>(list);            
             foreach  (db_userinfo single  in  temp)
             {
                 List<db_userinfo> tmpChildren = findallchildren(single.user_id);                          if  (tmpChildren.Count != 0)
                 {
                     list.AddRange(tmpChildren);
                 }
             }            
             return  list;
         }

这样,在页面的后台代码.cs文件中,就可以直接把这个方法的返回值作为条件查询中基础数据集。如

1
var  result =  from  in  findallchildren(userid)   where ..... select ....;

应该还有更好的方法,希望比较懂的朋友能多传授一下,欢迎盖楼!~










本文转自 我不会抽烟 51CTO博客,原文链接:http://blog.51cto.com/zhouhongyu1989/1428092,如需转载请自行联系原作者

目录
相关文章
|
30天前
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
99 6
|
30天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
253 0
|
2月前
|
SQL JavaScript 程序员
数据库LIKE查询屡试不爽?揭秘大多数人都忽视的秘密操作符!
本文分析了因数据库中的不可见空白字符导致的数据查询问题,探讨了问题的成因与特性,并提出了使用 SQL 语句修复问题的有效方案。同时,总结了避免类似问题的经验和注意事项。
46 0
|
2月前
|
存储 缓存 网络协议
数据库执行查询请求的过程?
客户端发起TCP连接请求,服务端通过连接器验证主机信息、用户名及密码,验证通过后创建专用进程处理交互。服务端进程缓存以减少创建和销毁线程的开销。后续步骤包括缓存查询(8.0版后移除)、语法解析、查询优化及存储引擎调用,最终返回查询结果。
44 6
|
2月前
|
开发框架 .NET 测试技术
C# 一分钟浅谈:GraphQL 数据类型与查询
本文介绍了GraphQL的基本概念、数据类型及查询方法,重点从C#角度探讨了GraphQL的应用。通过Hot Chocolate库的实例,展示了如何在ASP.NET Core中实现GraphQL API,包括安装、定义Schema、配置及运行项目。文中还讨论了常见问题与解决方案,旨在帮助开发者更好地理解和使用GraphQL。
57 2
|
3月前
|
JSON JavaScript 关系型数据库
node.js连接GBase 8a 数据库 并进行查询代码示例
node.js连接GBase 8a 数据库 并进行查询代码示例
|
3月前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
|
3月前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(下)
本文接续前文,深入讲解了在Windows环境下使用C#和ADO.NET操作南大通用GBase 8s数据库的方法。通过Visual Studio 2022创建项目,添加GBase 8s的DLL引用,并提供了详细的C#代码示例,涵盖数据库连接、表的创建与修改、数据的增删查改等操作,旨在帮助开发者提高数据库管理效率。
|
3月前
|
开发框架 .NET API
以C#一分钟浅谈:GraphQL 数据类型与查询
本文从C#开发者的角度介绍了GraphQL的基本概念、核心组件及其实现方法。GraphQL由Facebook开发,允许客户端精确请求所需数据,提高应用性能。文章详细讲解了如何在C#中使用`GraphQL.NET`库创建Schema、配置ASP.NET Core,并讨论了GraphQL的数据类型及常见问题与解决方案。通过本文,C#开发者可以更好地理解并应用GraphQL,构建高效、灵活的API。
138 64
|
3月前
|
存储 缓存 固态存储
怎么让数据库查询更快
【10月更文挑战第28天】
53 2