2011-12-22 76 views
0

我對linq to sql非常陌生,需要一點幫助。Linq To Sql - 返回表結果和計數

基本上我在C#中建立一個留言板。我有3個數據庫表 - 基本信息如下。

論壇 forumid 名

THREADS 線程ID forumid 標題 用戶ID

帖子 帖子ID 線程ID 文本 用戶ID 日期

基本上我想帶回我需要的一切在一個查詢中。我想列出一個THREADS頁面(針對特定的FORUM),並顯示該THREAD行中的POSTS數量以及最後一次POST的時間。

目前,我回來了所有THREADS,然後遍歷每個結果集,並單獨調用POST表中的線程和最新帖子的POST計數,但顯然這會導致問題在留言板越來越大的情況下擊中數據庫。

我的Linq到至今SQL:

public IList<Thread> ListAll(int forumid) 
    { 
     var threads = 
      from t in db.Threads 
      where t.forumid == forumid 
      select t; 
     return threads.ToList(); 
    } 

basicaly我現在需要得到每個線程職位的數量和每個線程的最後一個職位的日期。

任何幫助將是非常讚賞:)

編輯

人喜。感謝迄今爲止的幫助。基本上我幾乎在那裏。但是,在我最初的問題中,我留下了一個重要部分,因爲我需要檢索製作最後一個POST的人員的用戶名。因此,我需要在USERS表上與u.userid一起使用p.userid。到目前爲止,我有以下的,但只需要修改本加盟POST表與用戶表:

public IList<ThreadWithPostInfo> ListAll(int forumid) 
    { 
     var threads = (from t in db.Threads 
            where t.forumid == forumid 
            join p in db.Posts on t.threadid equals p.threadid into j 
         select new ThreadWithPostInfo() { thread = t, noReplies = j.Count(), lastUpdate = j.Max(post => post.date) }).ToList(); 
     return threads; 
    } 

UPDATE:

public IList<ThreadWithPostInfo> ListAll(int forumid) 
    { 
     var threads = (from t in db.Threads 
         from u in db.Users 
         where t.forumid == forumid && t.hide == "No" && t.userid == u.userid 
            join p in db.Posts on t.threadid equals p.threadid into j 
         select new ThreadWithPostInfo() { thread = t, deactivated = u.deactivated, lastPostersName = j.OrderByDescending(post => post.date).FirstOrDefault().User.username, noReplies = j.Count(), lastUpdate = j.Max(post => post.date) }).ToList(); 
     return threads; 
    } 

我終於想通它的一部分了,非常感謝所有你們:)。我現在唯一的問題是搜索結果方法。目前,它是這樣的:

public IList<Thread> SearchThreads(string text, int forumid) 
    { 
     var searchResults = (from t in db.Threads 
          from p in db.Posts 
          where (t.title.Contains(text) || p.text.Contains(text)) && t.hide == "No" 
          && p.threadid == t.threadid 
          && t.forumid == forumid 
          select t).Distinct(); 
     return searchResults.ToList(); 
    } 

請注意,我需要在where子句進入新的LINQ代碼:

 where (t.title.Contains(text) || p.text.Contains(text)) && t.hide == "No" 

所以將這一條款列入新的LINQ方法。任何幫助感激地接受:)

SOLUTION:

我想出了一個解決方案,但我不知道它最好的,最有效的。也許你們可以告訴我,因爲我仍然對linq很感興趣。詹姆斯·我想你的答案是最接近的,並讓我到附近的地方,我想是 - 感謝:)

public IList<ThreadWithPostInfo> SearchThreads(string text, int forumid) 
    { 
     var searchResults = (from t in db.Threads 
          from p in db.Posts 
          where (t.title.Contains(text) || p.text.Contains(text)) && t.hide == "No" 
          && p.threadid == t.threadid 
          && t.forumid == forumid 
          select t).Distinct(); 

     //return searchResults.ToList();   

     var threads = (from t in searchResults 
          join p in db.Posts on t.threadid equals p.threadid into j 
         select new ThreadWithPostInfo() { thread = t, lastPostersName = j.OrderByDescending(post => post.date).FirstOrDefault().User.username, noReplies = j.Count(), lastUpdate = j.Max(post => post.date) }).ToList(); 
     return threads; 
    } 
+0

由於您是LINQ的新手,我強烈建議您訪問http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b。當試圖弄清楚如何做這件事時,這非常有幫助。 – JamieSee 2011-12-22 18:22:36

回答

0

我想你真正需要的是這樣的:

 var threadsWithPostStats = from t in db.Threads 
            where t.forumid == forumid 
            join p in db.Posts on t.threadid equals p.threadid into j 
            select new { Thread = t, PostCount = j.Count(), LatestPost = j.Max(post => post.date) }; 

每您的評論和更新的問題,我加入此重申:

 var threadsWithPostsUsers = from t in db.Threads 
            where t.forumid == forumid 
            join p in db.Posts on t.threadid equals p.threadid into threadPosts 
            let latestPostDate = threadPosts.Max(post => post.date) 
            join post in db.Posts on new { ThreadID = t.threadid, PostDate = latestPostDate } equals new { ThreadID = post.threadid, PostDate = post.date} into latestThreadPosts 
            let latestThreadPost = latestThreadPosts.First() 
            join u in db.Users on latestThreadPost.userid equals u.userid 
            select new { Thread = t, LatestPost = latestThreadPost, User = u }; 
+0

嗨,詹姆斯。我認爲你的答案與我所尋找的最接近。我編輯了我的問題,因爲我需要在線程中獲取最新帖子的用戶名。任何援助/指針將不勝感激,因爲我只是不能完全明白:) – user1112150 2011-12-23 10:37:20

+0

@ user1112150我已更新我的答案以反映您的其他標準。乾杯! – JamieSee 2011-12-23 21:52:18

1
public IList<Thread> ListAll(int forumid) 
    { 
     var threads = 
      from t in db.Threads 
      where t.forumid == forumid 
      select new 
        { 
         Thread = t, 
         Count = t.Post.Count, 
         Latest = t.Post.OrderByDescending(p=>p.Date).Select(p=>p.Date).FirstOrDefault() 
        } 
    } 

應該是類似的東西

1

五月數據庫會話過多會話....

調用數據庫,.無論是查詢還是寫入,都是遠程調用,我們希望儘可能減少遠程調用的數量。當分析器發現單個會話正在對數據庫進行過多次調用時,會引發此警告。這通常表示會話使用方式的潛在優化。

有幾個原因,這可能是:

  • 大量查詢作爲一個選擇N + 1
  • 結果調用在一個循環
  • 更新數據庫(或插入/刪除)大量實體
  • 大量的,我們執行的執行我們的任務(不同的)查詢

出於第一個原因,您可以看到Select N + 1的建議。選擇N + 1是數據訪問反模式,其中數據庫以次優方式訪問。在此代碼示例看看:

// SELECT * FROM Posts 
var postsQuery = from post in blogDataContext.Posts 
       select post; 

foreach (Post post in postsQuery) 
{ 
    //lazy loading of comments list causes:  
    // SELECT * FROM Comments where PostId = @p0 
    foreach (Comment comment in post.Comments) 
    {  
     //print comment... 
    } 
} 

在這個例子中,我們可以看到,我們正在加載的職位名單(第一選擇),然後遍歷對象圖。但是,我們以懶惰的方式訪問該集合,導致Linq to Sql進入數據庫並將結果一次返回一行。這非常低效,Linq to Sql Profiler會在遇到這種情況時生成警告。

這個例子的解決方案很簡單。使用DataLoadOptions類強制加載集合,以指定我們想要加載的對象模型的哪些部分。

var loadOptions = new DataLoadOptions(); 
loadOptions.LoadWith<Post>(p => p.Comments); 
blogDataContext.LoadOptions = loadOptions; 

// SELECT * FROM Posts JOIN Comments ... 
var postsQuery = (from post in blogDataContext.Posts 
       select post); 

foreach (Post post in postsQuery) 
{ 
    // no lazy loading of comments list causes  
    foreach (Comment comment in post.Comments) 
    {  
     //print comment... 
    } 
} 

下一個被更新大量實體的使用聲明配料進行了討論,並可以通過使用PLINQO項目,該項目是一個集了LINQ的頂部SQL擴展來實現。將項目作爲一組存儲在緩存中將會有多酷。那麼,猜猜看! PLINQO很酷!將項目存儲在緩存中時,只需告訴PLINQO查詢結果需要屬於一個組並指定名稱。使緩存無效是分組真的出現的地方。當它們在組中時,高速緩存和在該高速緩存上採取的動作沒有耦合。看看這個例子:

public ActionResult MyTasks(int userId) 
{ 
    // will be separate cache for each user id, group all with name MyTasks 
    var tasks = db.Task 
     .ByAssignedId(userId) 
     .ByStatus(Status.InProgress) 
     .FromCache(CacheManager.GetProfile().WithGroup("MyTasks")); 

    return View(tasks); 
} 

public ActionResult UpdateTask(Task task) 
{ 
    db.Task.Attach(task, true); 
    db.SubmitChanges(); 

    // since we made an update to the tasks table, we expire the MyTasks cache 
    CacheManager.InvalidateGroup("MyTasks"); 
} 

PLINQO支持查詢配料的概念,使用稱爲期貨的功能,它允許你採取幾種不同的查詢和他們在一個單一的遠程調用發送到數據庫。這可以顯着減少您進行的遠程調用數量,並顯着提高您的應用程序性能。

cmiiw^_^