2009-04-14 72 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