簡短說明
加載它在列表看來部分你的問題可能看起來比較棘手,那就是如何以與LINQ to SQL(從此處出來的「L2S」)查詢爲匿名類一樣的方式填充自定義類。
根據您foreach
循環我猜你的自定義類是類似於這些:
public class PostType
{
public int PostId { get; set; }
public List<PostComment> PostComments { get; set; }
}
public class PostComment
{
public int CommentId { get; set; }
public string Title { get; set; }
}
LINQ查詢應相當於該T-SQL語句:
SELECT P.post_id, C.id, C.title
FROM post As P, comment As C
WHERE
P.post_id = @PostId
AND P.post_isdeleted = 0 -- 0 is false
AND C.CommentPostID = P.post_id
不像L2S版本(請參閱下面的詳細解釋部分以獲取更多信息),則此語句將返回一個展平結果,每行包含一個P.post_id
,C.id
和C.title
。如果你的類以相同的方式代表一個入口,這將很容易解決(我不主張這樣的設計;我只是在評論設計如何改變它如何填充)。類中的層次關係改變了事物。
此外,您的代碼顯示List<PostType>
,但不需要列表,因爲總是會有一個PostType
,因爲您在post_id
上進行篩選。如果該條件被刪除,則,然後您可能會在滿足其他條件的情況下獲得與具有不同PostIds的多個匹配項。如果是這種情況,下面的代碼將需要更改。
也就是說,讓我們跳入一些ADO.NET並使用SqlDataReader填充類。
int postIdInput = 42; // desired post_id to search for
// PostType delcared prior to getting the results
PostType postType = new PostType()
{
PostId = postIdInput,
PostComments = new List<PostComment>()
};
// Database interaction starts here...
// updated SQL statement to use column name aliases for clarity when used by the SqlDataReader
string sqlStatement = @"SELECT P.post_id As PostId, C.id As CommentId, C.title As Title
FROM post As P, comment As C
WHERE
P.post_id = @PostId
AND P.post_isdeleted = 0 -- 0 is false
AND C.CommentPostID = P.post_id";
string sqlConnectionString = "..."; // whatever your connection is... probably identical to your L2S context.Connection.ConnectionString
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
SqlCommand command = new SqlCommand(sqlStatement, conn);
command.Parameters.AddWithValue("@PostId", postIdInput); // use Parameters.Add() for greater specificity
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// postId was set based on input, but could be set here as well although it would occur repeatedly
// if desired, uncomment the 2 lines below and there's no need to initialize it earlier (it'll be overwritten anyway)
//int postId = Int32.Parse(reader["PostId"].ToString());
//postType.PostId = postId;
int commentId = Int32.Parse(reader["CommentId"].ToString());
string title = reader["Title"].ToString();
// add new PostComment to the list
PostComment postComment = new PostComment
{
CommentId = commentId,
Title = title
};
postType.PostComments.Add(postComment);
}
// done! postType is populated...
}
// use postType...
這應該涵蓋您的方案。但是,要獲得更詳細的答案,請繼續閱讀!
詳解(又名「授人以漁。」)
比方說,你無法弄清楚如何獲得等價的SQL語句。儘管有不同的方式可以這樣做,但我會專注於您正在使用L2S並探索一些相關選項的事實。
第1步:轉換LINQ查詢到SQL (通過 「欺騙」)
你很幸運,因爲有一個快捷方式。將現有的LINQ表達式轉換爲SQL比向後翻譯SQL和LINQ更方便。
您可以通過使用這些DataContext的選項從您的代碼轉換的T-SQL語句:
注:我沒有說這是一條捷徑。 SQL的知識很好理解,並且要清楚我並不是建議盲目使用生成的輸出。當然,SQL可能與您期望的有所不同,但它提供了一個體面的起點。如果需要,你可以調整它。
使用這些方法中的任何一種並複製結果 - 您將需要它的步驟2。
實施例DataContext.GetCommand()的用法:
var query = /* your L2S query here */;
string sqlStatement = context.GetCommand(query).CommandText; // voila!
要獲得的結果要麼設置斷點和複製其值,檢查出來在立即窗口,或某處顯示它(Console.WriteLine等等。)。
例DataContext.Log用法:在這種情況下執行將轉儲到控制檯窗口的SQL語句
context.Log = Console.Out;
查詢。你可以從那裏複製它。在其他地方把它們扔掉,比如到調試輸出窗口,請查看以下鏈接:
第2步:在手的SQL語句,在ADO.NET中使用它
現在您已經擁有了SQL語句,我們可以在ADO.NET中使用它。當然你也可以使用存儲過程,並且不應該很難替代它。
在使用它之前,您可能需要清理聲明。我用了一個類似的查詢本地得到這個和你生成的語句可能類似於此:
SELECT [t0].[post_id], [t1].[id], [t1].[title], (
SELECT COUNT(*)
FROM [comment] AS [t2]
WHERE [t2].[id] = [t0].[post_id]
) As [value]
FROM [post] As [t0]
LEFT OUTER JOIN [comment] As [t1] ON [t1].[CommentPostID] = [t0].[post_id]
WHERE ([t0].[post_id] = @p0) AND ([t0].[post_isdeleted] = 0)
ORDER BY [t0].[post_id], [t1].[id]
通知嵌入式SELECT COUNT(*)? L2S查詢從未請求計數,但結果請求連接上使用的相同ID的計數。另請注意,這些列沒有別名。你會根據它們的實際名稱來參考這些列(即post_id
與PostId
)。另外,SQL參數被命名爲@ p0 ... @ pn,並且應用默認排序順序。您可以將其複製/粘貼到之前使用的SqlDataReader中,但您需要重命名要匹配的列和參數。
一個清理的上述版本與註釋掉重命名的參數和不必要的部分轉載如下(如果這種方法是採取測試,以確保它相當於預計的):
SELECT [P].[post_id] As PostId, [C].[id] As CommentId, [C].[title] As Title--, (
-- SELECT COUNT(*)
-- FROM [comment] AS [t2]
-- WHERE [t2].[id] = [t0].[post_id]
--) As [value]
FROM [post] As [P]
LEFT OUTER JOIN [comment] As [C] ON [C].[CommentPostID] = [P].[post_id]
WHERE ([P].[post_id] = @PostId) AND ([P].[post_isdeleted] = 0)
--ORDER BY [t0].[post_id], [t1].[id]
以上現在可以與之前的SqlDataReader一起使用。
如果L2S查詢是在一個SelectMany的格式,如可能已經產生更直接的查詢:
var query = from arow in context.post
from c in context.comment
where arow.post_id == id && arow.post_isdeleted == false
&& c.CommentPostID == arow.post_id
select new
{
arow.post_id,
c.id,
c.title
};
的L2S的SelectMany查詢生成類似下面的SQL語句:
SELECT [t0].[post_id], [t1].[id], [t1].[title]
FROM [post] As [t0], [comment] As [t1]
WHERE ([t0].[post_id] = @p0) AND ([t0].[post_isdeleted] = 0)
AND ([t1].[CommentPostID] = [t0].[post_id])
LINQPad
雖然這個詳細的解釋看起來就非常困難,有一個輕鬆掌握這些信息。如果你還沒有給LINQPad一個嘗試,那麼我強烈推薦它 - 它也是免費的! LINQPad將向您顯示您的L2S查詢結果,具有查看生成的SQL的SQL選項卡,並顯示使用的lambda表達式(上述查詢語法顯示爲等效的lambda/extension)。最重要的是,它是用於C#/ VB.NET(包括LINQ to Objects/XML)的通用工具,以及具有數據庫支持的SQL編碼等等。
這裏是LINQPad的一個微小的屏幕截圖顯示了一些前面討論的主題:
我不想佔用更多的頁面空間比我已經有這麼click here to see the image in its original size。
如果您到此爲止,恭喜!:)
你正在使用什麼SQL?如果你使用t-sql,答案將不會像你使用plsql一樣。 – ALOToverflow 2010-01-20 17:31:07
我正在使用sql server – Luke101 2010-01-20 17:48:17