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>类型
最开始我是这样去写的
/*大错特错*/
var list = from ....... where.... select...;
.....
return list.ToList<T>();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
现在看看我还是挺有创造力的哈,居然能写出这么个东西。
首先不说list.ToList<T>();本身就画红线,为什么我要在最后 return 的时候才去ToList()呢?原因是我知道var 可以用“+=”运算符。这样递归的时候将深一层的返回值直接+到一起,用起来方便一些。
啊~真是大错特错了,首先,按照我的思路,深一层返回的值已经是ToList类型了,所以不能再用+=运算符了.其次,好吧,我承认,我还是没有太了解var是个什么东西。其实在程序运行之后,list就会有一个明确的类型,是系统去自动判定出来的。var只是使我们编程的时候更方便一些,有点像程序蜜糖(忘记是从哪听来的了),也就是说系统应该能识别出list是一个T类型对象的集合,而我这么写就有点画蛇添足的意味了。
正解:
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一个对象,而不是直接声明之后赋值,否则跟没写一样。
List<T> tmpList = list; //错误 List<T> tmpList = new List<T>(list);//正确
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
最后完整的代码为:
contextdata ctdt = new contextdata();
public static List<db_userinfo> findallchildren(int parentid)
{
var list = (from c 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;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
这样,在页面的后台代码.cs文件中,就可以直接把这个方法的返回值作为条件查询中基础数据集。如
var result = from c in findallchildren(userid) where.....select....;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
应该还有更好的方法,希望比较懂的朋友能多传授一下,欢迎盖楼!~
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
C# 使用Linq递归查询数据库遇到的问题及解决方法的更多相关文章
- 关于php读mysql数据库时出现乱码的解决方法
关于php读mysql数据库时出现乱码的解决方法 php读mysql时,有以下几个地方涉及到了字符集. 1.建立数据库表时指定数据库表的字符集.例如 create table tablename ( ...
- mysql5.x升级到mysql5.7后导入之前数据库date出错的快速解决方法【mysql低版本数据导入到高版本出错的解决方法】
mysql5.x升级至mysql5.7后导入之前数据库date出错,这是由于MySQL的sql_mode的影响,解决方法如下所示: [具体参考:mysql的sql_mode详解]修改mysql5.7的 ...
- Navicat连接阿里云(centos7.3)的MySQL数据库遇到的问题及解决方法
注:本文涉及到的解决方案都是我遇到的问题的对应解决方案,不一定适用于每一个人,如果问题仍然存在,请继续百度查询其他解决方法 1. 首先是登录阿里云MySQL的一些必要信息(登录其他云主机的mysql ...
- informix 数据库锁表分析和解决方法
一.前言 在联机事务处理(OLTP)的数据库应用系统中,多用户.多任务的并发性是系统最重要的技术指标之一.为了提高并发性,目前大部分RDBMS都采用加锁技术.然而由于现实环境的复杂性,使用加锁技术又不 ...
- Oracle11g数据库导入到oracle10g的解决方法
我想有很多人在工作和学习中遇到这样的一个问题,Oracle数据库服务器版本和本机版本不一致问题,你的本机要是比服务器的版本要高的话还好,如果你本机是10g服务器是11g的话,从11g导出来的数据库是导 ...
- SQL SERVER数据库附加是只读的解决方法
使用sa登录SQL Server2008附加数据库,附加之后数据库为只读的, 点数据库-->“属性”-->“选项”-->“状态”, 发现“数据库为只读”这一项为True,改为fals ...
- oracle9i的erp数据库无法正常关闭的解决方法。
oracle9i版本的ERP数据库无法正常关闭. 场景描述:oracle9i数据库正常关闭的时候,hang住在一个地方无法正常关闭. 解决思路:查看alert日志,分析问题. [oraprod@erp ...
- MySQL数据库性能优化思路与解决方法(二转)
原文:http://bbs.landingbj.com/t-0-242512-1.html 1.锁定表 尽管事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是 ...
- MySQL数据库性能优化思路与解决方法(一转)
1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越 小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设 ...
随机推荐
- swift:入门知识之协议与扩展
swift中使用protocol声明一个协议接口 swift中类.枚举和结构体都可以实现协议接口 swift中类中的方法都可以修改成员变量的值 swift中结构体中的方法默认是不能修改成员变量的,添加 ...
- mysql 生成批量存储过程
CREATE PROCEDURE `BatchInsert`(IN init INT, IN loop_time INT)BEGIN DECLARE Var INT; DECLARE ID INT; ...
- 【推荐】HTML5 UI框架 推荐
笔者的男装网店:http://shop101289731.taobao.com .冬装,在寒冷的冬季温暖你.新品上市,环境选购 最近自己瞎搞一下web网页的东西.想开发先找资源. 整理了一下HTML5 ...
- 运行java -version报cannot restore segment prot after reloc: Permission denied
linux 安装jdk1.6后,运行java -version,没有出现相关的版本信息,而是出现了以下错误: dl failure on line 685Error: failed /usr/loca ...
- USACO Section 2.4: Bessie Come Home
因为题目给了边的信息,所以比较适用bell-man的方法 /* ID: yingzho1 LANG: C++ TASK: comehome */ #include <iostream> # ...
- dataTables表格分页排序等交互
官网: https://www.datatables.net/ 中文参考网站: http://datatables.club/ datatables+bootstrap示例: http://sandb ...
- [HIHO1039]字符消除(字符串,枚举,模拟)
题目链接:http://hihocoder.com/problemset/problem/1039 思路:枚举所有字符更新的位置和ABC三种修改方案,之后再模拟消除规则,一步一步去消除.直到无法消除, ...
- vi 每日练习
vi 1. 4 空格 2. ctrl + b, ctrl + f 3. 0 $ 4. 1G gg G 5. 10G 6. 10 回车 7. / ? 8. ...
- Css中光标,DHTML,缩放的使用
Css中光标的使用: 属性名称 属性值 说明cursor ...
- 瞎折腾之 Lucene.Net + MVC 搜索功能(上)
前言 首先,关于Lucene.Net 的文章已经很多了.我这次决定写出来只是为了练练手,虽然在别人看来没什么用,但是自己确实是手动实践了一把.我个人觉得还是有意义的.爱折腾.敢于实践.才能有所收获,才 ...