2009-04-14 70 views
1

比方說,我有三個表:LINQ到SQL表合併

用戶

 
ID | Name 
=========== 
1 | UserA 
----------- 
2 | UserB 
----------- 

設置

 
ID | Name  | Default 
========================= 
1 | SettingA | ADefault 
------------------------- 
2 | SettingB | BDefault 
------------------------- 

而且

UserSetting

 
UserID | SettingID | Value 
================================ 
1  | 1  | Alice 
-------------------------------- 
1  | 2  | Bob 
-------------------------------- 
2  | 1  | AOverride 
-------------------------------- 

當我創建我的dbml文件時,根據數據庫中設置的外鍵將用戶適當地鏈接到UserSettingUserSettingSetting

我想知道的是,如果用戶沒有以某種合理的方式明確覆蓋值,它是否可以從UserSetting合併回Setting表。

具體來說,我正在尋找以下僞代碼:

var user = MyDataContext.Users.SingleOrDefault(u => u.ID == 2); 

foreach(var setting in user.UserSettings) 
{ 
    Console.Writeline(setting.ID + "|" + setting.Value); 
} 

要輸出是這樣的:

 
1 | AOverride 
2 | BDefault 

不用做任何修改,user.UserSettings將只包含有值專門被覆蓋,所以它只會返回:

 
1 | AOverride 

任何想法?或者有更多代表的人請幫助我重述一下,因爲它可能不完全清楚? :)

回答

3

我喜歡保持的LINQ到SQL很簡單化,並添加任何花哨的要求到我的部分課程,以下是我使用的解決方案。

我添加了下面的幫助到我的User類(基於聖何塞的答案,但固定的所以它的工作原理):

public IEnumerable<SettingValue> GetSettingsWithDefaults(IEnumerable<Setting> settings) 
{ 
    return from s in settings 
      join us in this.UserSettings 
      on s.ID equals us.SettingID into userSettings 
      from us in userSettings.DefaultIfEmpty() 
      select new SettingValue 
        { 
         Setting = s, 
         Value = (us == null) ? s.Default : us.Value, 
         IsDefault = (us == null) 
        }; 
} 

這需要一個新的類:

public class SettingValue 
{ 
    public Setting Setting { get; set; } 
    public string Value { get; set; } 
    public bool IsDefault { get; set; } 
} 

然後我可以做如下:

foreach(var userSetting in user.GetSettingsWithDefaults(settings)) 
{ 
    Debug.WriteLine(string.Format("Name:{0}, Value:{1}, IsDefault:{2}", 
     userSetting.Setting.Name, 
     userSetting.Value, 
     userSetting.IsDefault 
    )); 
} 

這給了我以下輸出

Name:SettingA, Value:OverrideA, IsDefault:False 
Name:SettingB, Value:DefaultB, IsDefault:True 
+0

這工作完美。我做了一個我認爲有幫助的小調整。而不是在linq查詢中設置IsDefault,SettingValue中的get僅返回(Setting.Default == Value)。 – jerhinesmith 2009-04-15 16:10:40

-1

您可以創建一個視圖,加入UserSetting和設置代表每個用戶的所有設置。然後,除了UserSettings關聯外(或者取而代之),還可以在DBML文件中使用視圖(除非希望能夠添加新設置,否則您可能希望UserSettings關聯也可以)。

我沒有SQL服務器方便,但認爲可能會是這個樣子:

SELECT 
    User.ID AS UserID, 
    Setting.ID AS SettingID, 
    COALESCE(UserSetting.Value, Setting.Default) AS Value, 
    CASE WHEN UserSetting.UserID IS NOT NULL THEN CAST(0 AS BIT) 
     ELSE CAST(1 AS BIT) END AS IsDefault 
FROM User 
    CROSS JOIN Setting 
    LEFT JOIN UserSetting ON Setting.ID = UserSetting.SettingID 
     AND UserSetting.UserID = User.ID