2011-07-31 92 views
1

我正在嘗試創建一個郵件系統(類似於gmail的東西),但這將用作私人郵件系統。不幸的是(對我來說),我一直在寫一個查詢,它會在列表視圖中顯示消息接收者的名字。LINQ to SQL查詢問題(無法獲得正確的值)

這裏是郵件系統的數據庫架構:

enter image description here

我相信該架構是非常清楚的,但讓我先簡單介紹一下每個表。 MailState表具有關於某個用戶的每封郵件的郵件位置(收件箱,發件人,垃圾箱)的數據。 MailStatus只有兩個狀態:「Read」或「New」。這是顯而易見的郵件表。

我最近幾個小時一直在嘗試的是在特定用戶的「已發送」郵箱中顯示郵件,而且我差不多已經完成了。問題是我不能讓我的查詢顯示正確的User.DisplayName,只要我檢查這是哪個郵箱(由登錄用戶的ID確定)。

這是我一直在使用的代碼:

var _messages = from m in db.MailState 
         select m; 

     if (mailboxType == "Inbox") 
     { 
      var mailbox = from m in _messages 
         where m.idUser == idUser 
         where m.Mail.idSender != idUser 
         where m.MailLocation.Name == mailboxType 
         select new { m.idMail, m.Mail.User.DisplayName, m.Mail.DateSent, m.Mail.Subject }; 

      lvMailbox.DataSource = mailbox; 
     } 
     else if (mailboxType == "Sent") 
     { 
      var mailbox = from m in db.MailState 
          where m.MailLocation.Name == mailboxType 
          select new { m.Mail.idSender, m.idMail, m.Mail.DateSent, m.Mail.Subject, m.User.DisplayName }; 

      //mailbox = mailbox.Where(m => m.idSender == idUser); 

      lvMailbox.DataSource = mailbox; 
     } 
     else 
     { 
      //NOTHING YET 
     }   

     lvMailbox.DataBind(); 

收件箱中工作正常,但「已發送」郵箱顯示已登錄的用戶,而不是顯示收件人名稱的名稱。最令我困擾的是,如果我的查詢不包含登錄用戶的where子句,它會正確顯示所有內容。這就是爲什麼我需要一些幫助。

P.S.歡迎任何其他建議(關於代碼,數據庫等)!

回答

2

在有兩條路徑,以「用戶」表的查詢可以得到非常混亂,導致的結果就像你與情況:

「已發送」郵箱顯示已登錄的名字而不是顯示收件人姓名的 。

在做多個查詢之前,我嘗試做的事情之一是嘗試展開查詢的源數據以使我的查詢更加簡潔。事情是這樣的:

var messages = 
    from ms in db.MailState 
    select new 
    { 
     idMail = ms.idMail, 
     Subject = ms.Mail.Subject, 
     DateSent = ms.Mail.DateSent, 
     Location = ms.MailLocation.Name, 
     Sender_idUser = ms.Mail.idSender, 
     Sender_DisplayName = ms.Mail.User.DisplayName, 
     Recipient_idUser = ms.idUser, 
     Recipient_DisplayName = ms.User.DisplayName, 
    }; 

現在,鑑於此,現有的查詢應該是這樣的:

/* Inbox */ 
var mailbox = 
    from m in messages 
    where m.Recipient_idUser == idUser 
    where m.Sender_idUser != idUser 
    where m.Location == mailboxType 
    select new 
    { 
     m.idMail, 
     m.Sender_DisplayName, 
     m.DateSent, 
     m.Subject 
    }; 

/* Sent */ 
var mailbox = 
    from m in messages 
    where m.Location == mailboxType 
    select new 
    { 
     m.Sender_idUser, 
     m.idMail, 
     m.DateSent, 
     m.Subject, 
     m.Recipient_DisplayName 
    }; 

這些應該是一個小更易於閱讀和推理。

所以從這裏我試圖想象表示發送和接收電子郵件所需的記錄。

比方說,我們有三個用戶安妮,比爾和本。如果安妮向Bill和Ben發送郵件,我的messages查詢將不得不返回三條記錄 - 一條用於安妮郵箱中的「已發送郵件」&每條郵件都爲Bill & Ben的「收件箱」。

 
Field     | Anne   | Bill  | Ben  | 
----------------------+--------------+------------+------------+ 
idMail    | 1   | 1   | 1   | 
Subject    | "Hi"   | "Hi"  | "Hi"  | 
DateSent    | 2011/08/01 | 2011/08/01 | 2011/08/01 | 
Location    | "Sent Items" | "Inbox" | "Inbox" | 
Sender_idUser   | 1   | 1   | 1   | 
Sender_DisplayName | "Anne"  | "Anne"  | "Anne"  | 
Recipient_idUser  | 1   | 2   | 3   | 
Recipient_DisplayName | "Anne"  | "Bill"  | "Ben"  | 

這告訴我是從當前數據庫結構中的數據沒有確定誰收件人是在用戶的「已發送郵件」文件夾中的項目所需的信息。實際上,它突出了「Recipient_ *」字段的命名問題。

這裏有一個更好的messages查詢開始查詢:

var messages = 
    from m in db.Mail 
    select new 
    { 
     idMail = m.idMail, 
     Subject = m.Subject, 
     DateSent = m.DateSent, 
     Sender = new 
     { 
      idUser = m.idSender, 
      DisplayName = m.User.DisplayName, 
     }, 
     Locations = 
      from ms in db.MailState 
      where ms.idMail == m.idMail 
      select new 
      { 
       Location = ms.MailLocation.Name, 
       idUser = ms.idUser, 
       DisplayName = ms.User.DisplayName, 
      }, 
     Recipients = 
      from ms in db.MailState 
      where ms.idMail == m.idMail 
      where ms.idUser != m.idSender 
      select new 
      { 
       idUser = ms.idUser, 
       DisplayName = ms.User.DisplayName, 
      }, 
    }; 

以此爲基礎的查詢,您現有的查詢現在可以是這樣的:

/* Inbox */ 
var mailbox = 
    from m in messages 
    from r in m.Recipients 
    where r.idUser == idUser 
    select new 
    { 
     m.idMail, 
     r.DisplayName, 
     m.DateSent, 
     m.Subject 
    }; 

/* Sent */ 
var mailbox = 
    from m in messages 
    where m.Sender.idUser == idUser 
    select new 
    { 
     m.Sender.idUser, 
     m.idMail, 
     m.DateSent, 
     m.Subject, 
     Recipients = 
      from r in m.Recipients 
      select r.DisplayName, 
    }; 

這些查詢都是相當有點簡單,應該很容易推斷他們是否正確。

無需過濾MailLocation字段,因爲這是現在在查詢本身捕獲到的信息。

您需要做的唯一事情就是將Recipients字段拼合成單個字符串進行數據綁定,因爲這是收件人顯示名稱的集合,而不僅僅是單個字符串。

我希望這有助於。

+0

你好!首先,我想感謝你的出色解釋和你的努力!當我看到你的回答很詳細時,我感到非常驚訝。但是,我遇到了一些麻煩。現在我的收件箱不起作用,即它與「已發送」郵箱具有相同的症狀(錯誤地命名爲發件人)。關於,發送郵箱我還沒有告訴你什麼,因爲,正如你告訴我做的,我試圖將收件人集合轉換爲單個字符串,但由於缺乏經驗,我卡住了,所以當我弄清楚如何得到它我會發布你的回覆!附:再次感謝您的回覆! ;) –

+0

沒問題。看看'String.Join(...)'。 – Enigmativity

+0

我遵循你的建議,使用'String.Join',並被綁定到listview。任何幫助,將不勝感激。這是代碼: 'foreach(var in mailbox) { foreach(string r in m.Recipients) { string idMail = m.idMail.ToString(); string DateSent = m.DateSent.ToString(); string Subject = m.Subject; string DisplayName = string.Join(「」,m.Recipients); } }' –

1

以下是一種方法,如果您能夠更改數據庫架構。

將新字段添加到標識郵件收件人的郵件表idRecipient中。 (郵件)的屬性,但作爲郵件的屬性存儲爲狀態。如果收件人能夠刪除郵件(郵件)的屬性,則該郵件的屬性爲狀態。該信息將從您的模式中完全刪除。)

一旦你有了這個字段,查詢就會變得更加簡單。

var mailbox = from m in db.MailState 
    where m.MailLocation.Name == mailboxType 
    where m.idUser == idUser 
    select new { m.Mail.idRecipient, 
       m.idMail, 
       m.Mail.DateSent, 
       m.Mail.Subject, 
       m.User.DisplayName /*or recipient display name*/ }; 

會這樣的方法嗎?

(響應編輯評論)

鑑於新的信息,有發送者和接收者之間的多到一的關係,接近這一個方法是使用子查詢。

var mailbox = from m in db.MailState 
    where m.MailLocation.Name == mailboxType 
    where m.idUser == idUser 
    select new { 
       Recipients = from z in db.MailState 
        where z.idMail == m.idMail // outer join on message ID 
        where z.idLocation.Id != mailboxType // exclude sender 
        select z.User, 
       m.idMail, 
       m.Mail.DateSent, 
       m.Mail.Subject, 
       m.User.DisplayName 
    }; 

然後mailbox.Recipients是IEnumerable<User>(取決於你的模型)包含消息的所有接收者。

(請注意,將收件人存儲在MailState中的要求要求永不從MailState中刪除記錄,因爲這是收件人信息的唯一存儲庫。)

+0

感謝您的回覆,但這不是解決方案,因爲它應該可以發送郵件給幾個收件人,在這種情況下,我會乘數據。 –

+0

我編輯了回覆,以反映允許多個收件人的要求。 – drf

+0

不幸的是,它仍然是一樣的。我仍然收到錯誤的收件人顯示名稱。 –