程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 使用Linq遞歸查詢數據庫遇到的相關問題及解決方法

C# 使用Linq遞歸查詢數據庫遇到的相關問題及解決方法

編輯:C#入門知識

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>();

現在看看我還是挺有創造力的哈,居然能寫出這麼個東西。

首先不說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);//正確

最後完整的代碼為:

        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;
        }

這樣,在頁面的後台代碼.cs文件中,就可以直接把這個方法的返回值作為條件查詢中基礎數據集。如

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

應該還有更好的方法,希望比較懂的朋友能多傳授一下,歡迎蓋樓!~

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved