Linq-to-SQL表合并

时间:2009-04-14 20:34:10

标签: c# linq-to-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文件时,它会根据数据库中设置的外键将User正确地链接到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

有什么想法吗?或者有更多代表的人请帮我改一下,因为它可能不是很清楚? :)

2 个答案:

答案 0 :(得分:3)

我喜欢让Linq-to-SQL相当愚蠢,并为我的部分类添加任何花哨的要求,以下是我使用的解决方案。

我将以下帮助器添加到我的User类中(基于Jose的答案,但已修复,因此它有效):

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

答案 1 :(得分:-1)

您可以创建一个连接UserSetting和Setting的视图,该视图代表每个用户的所有设置。然后在您的DBML文件中使用除了(或代替)UserSettings关联之外的视图(除非您希望能够添加新设置,否则您可能希望UserSettings关联也可以使用)。< / p>

我没有方便的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