2009-07-02 36 views
0

我試圖從數據庫中獲取消息的某個收件人與用戶匹配的消息列表。通常情況下,如果只有一個收件人,你會像下面如何LINQ當一個鍵是ArrayOfInt而另一個鍵時加入int

var res = db.messages.Where(m => m.id == message_id) 
       .Join(db.persons, m => m.recipients, p => p.id, (m, p) => new {m, p}) 
       .Select(x => new Message(){ msg = x.m, person = x.p}) 

但是,如果收件人什麼是一個逗號分隔的整數和id的字符串是一個整數?

+0

它無法完成。 http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/d2791ad4-3897-4fc0-80e9-72ebc4822898 – sean 2009-07-04 11:58:10

+0

以下內容可能也是有用的信息,http://tomasp.net /blog/linq-expand.aspx – sean 2009-07-06 06:50:38

回答

0

選項1 - 使用包含:

var res = from m in db.messages 
      where m.id == message_id 
      from p in db.persons 
      where m.recipients.Split(",").Select(i => Int32.Parse(i)) 
       .Contains(p.id) 
      select new Message() { 
       msg = m, 
       person = p 
      }; 

的想法:

  1. 獲取郵件作爲原始查詢
  2. 獲取其中包含在收件人列表中的所有人員
  3. 繼續與您原來的查詢

選項2 - 使用LINQ加入(也許複雜得多,它需要):

var res = from m in db.messages 
      where m.id == message_id 
      from r in m.recipients.Split(",") 
      select new { 
       Message = m, 
       Recipient = Int32.Parse(r) 
      } into rec 
      join p in db.persons on rec equals p.id 
      select new Message() { 
       msg = m, 
       person = p 
      }; 

的想法:

  1. 獲取郵件作爲原始查詢
  2. 斯普利特將該字符串轉換爲Int32列表
  3. 加入此列表對抗db.persons
  4. 繼續您的o riginal查詢

不知道其中哪些是快,你必須檢查。

我也會迴避使用逗號分隔的字符串作爲外鍵參考,因爲您在這裏遇到了麻煩。他們看起來很醜陋,而且操縱真正的痛苦。相反,如果您可以控制架構,請考慮一個具有MessageIdPersonId的一對多關係表。當然,如果你沒有控制權,你就會陷入困境。

聲明:這些未經測試,因此可能需要對代碼進行一些調整才能使用。算法應該沒問題。

+0

我最初過分簡化了查詢,現在應該更清楚了。 – sean 2009-07-02 00:55:51

1

您需要將收件人轉換爲元素列表作爲開始。我假設收件人是來自人員表格的ID列表。因此,從你的問題你必須傳入人員ID做一個選擇呢?

var messages=db.messages.Select(
     m => m.id == message_id && 
     (m.recipients.Split(","). 
      Any(recipient => reipient == person_id) 
     ) 

var person = db.Persons.Select(p => p.id == person_id) 

注意,在LINQ這樣做是要吃虧的性能損失象外之象.Split是C#,不會對IQueryable的工作。因此,數據庫將不得不傳輸大量數據來執行此查詢,具體取決於表的大小。如果您在將數據庫標記爲已存在數據庫時擁有數據庫視圖,或者您可以在數據庫中創建一個包含消息標識符的消息收件人的新表格,則可以更輕鬆地完成此操作(而不是在過程中提到正常化你的數據庫)。

相關問題