方法'Boolean Contains(System.DayOfWeek)'没有支持的SQL转换

时间:2012-01-18 19:50:08

标签: linq-to-sql xaml windows-phone

在我的Windows Phone Mango应用程序中,我有一堆复选框,每个复选框对应一周中的某一天。我想过滤我查询的数据,选中哪个复选框。这就是我想出来的,但我觉得有更好的解决方案:

声明XAML中的复选框:

            <CheckBox Content="Mon" x:Name="MonCheckbox" Checked="DayCheckbox_Tap" Unchecked="DayCheckbox_Tap"/>
            <CheckBox Content="Tue" x:Name="TueCheckbox" Grid.Column="1" Checked="DayCheckbox_Tap" Unchecked="DayCheckbox_Tap" />
            <CheckBox Content="Wed" x:Name="WedCheckbox" Grid.Column="2" Checked="DayCheckbox_Tap" Unchecked="DayCheckbox_Tap" />
            <CheckBox Content="Thur" x:Name="ThurCheckbox"  Grid.Row="1" Checked="DayCheckbox_Tap" Unchecked="DayCheckbox_Tap" />
            <CheckBox Content="Fri" x:Name="FriCheckbox" Grid.Row="1" Grid.Column="1" Checked="DayCheckbox_Tap" Unchecked="DayCheckbox_Tap" />
            <CheckBox Content="Sat" x:Name="SatCheckbox" Grid.Row="1" Grid.Column="2" Checked="DayCheckbox_Tap" Unchecked="DayCheckbox_Tap" />
            <CheckBox Content="Sun" x:Name="SunCheckbox" Grid.Row="2" Grid.Column="0" Checked="DayCheckbox_Tap" Unchecked="DayCheckbox_Tap" />

将一天与每个复选框相关联:

    public MainPage()
    {
        InitializeComponent();

        LayoutRoot.DataContext = this;

        // This is grossly imperative. Can it be done in XAML?
        MonCheckbox.Tag = DayOfWeek.Monday;
        TueCheckbox.Tag = DayOfWeek.Tuesday;
        WedCheckbox.Tag = DayOfWeek.Wednesday;
        ThurCheckbox.Tag = DayOfWeek.Thursday;
        FriCheckbox.Tag = DayOfWeek.Friday;
        SatCheckbox.Tag = DayOfWeek.Saturday;
        SunCheckbox.Tag = DayOfWeek.Sunday;

        // ...
    }

维护当前所选日期的集合:

    ICollection<DayOfWeek> _selectedDays = new Collection<DayOfWeek>();

    private void DayCheckbox_Tap(object sender, RoutedEventArgs e)
    {
        CheckBox checkbox = (CheckBox)sender;
        if (_selectedDays.Contains((DayOfWeek)checkbox.Tag))
        {
            _selectedDays.Remove((DayOfWeek)checkbox.Tag);
        }
        else
        {
            _selectedDays.Add((DayOfWeek)checkbox.Tag);
        }

        refreshCheckinData();
    }

当我去刷新显示给用户的数据时,问题出现了:

    private void refreshCheckinData()
    {
        Checkins.Clear();
        Checkins.AddAll(from checkin in checkinData.Items
                        where _selectedDays.Contains(checkin.DateTime.DayOfWeek)
                        select checkin);
    }

public static class ExtensionMethods
{
    public static void AddAll<T>(this ICollection<T> dest, IEnumerable<T> source)
    {
        if (dest == null)
        {
            throw new ArgumentNullException("dest");
        }

        foreach (T t in source)
        {
            dest.Add(t);
        }
    }
}

当代码尝试在source中迭代AddAll()时,会发生以下异常:

Method 'Boolean Contains(System.DayOfWeek)' has no supported translation to SQL."   System.Exception {System.NotSupportedException}

我该如何解决这个问题?为什么Contains需要SQL翻译?是否有更好的方法来处理这一切,使用更多的声明性XAML和更少命令性的代码隐藏?

更新:我尝试将查询更改为:

where _selectedDays.Any(day => day == checkin.DateTime.DayOfWeek)

现在我收到以下错误:

"Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator." System.Exception {System.NotSupportedException}

_selectedDays在内存中定义。为什么需要将其翻译成SQL?

2 个答案:

答案 0 :(得分:0)

如果我理解正确,那么你想把所有选定的日子添加到你的'Chekings'中,为什么你不尝试这个代码,我认为这将解决你现在的问题,并回答我必须考虑的其他问题他们有点做一些研究。 :)

foreach(var day in _selectedDays)
{
 Checkins.AddAll(from checkin in checkinData.Items
                    where checkin.DateTime.DayOfWeek == day
                    select checkin);
}

必须测试这个,我不知道它是否有效或是否有效。

from checkin in checkinData.Items
join sdays in _selectedDays on checkin.DateTime.DayOfWeek == sdays
select checkin

答案 1 :(得分:0)

您的原始查询已结束。我认为ICollection上的Contains()方法正在妨碍SQL转换器 - 我需要仔细检查代码才能确定。

您可以通过将代码更改为强制选择Enumerable.Contains()扩展方法来解决此问题:

    private void refreshCheckinData()
{
    Checkins.Clear();
    Checkins.AddAll(from checkin in checkinData.Items
                    where _selectedDays.AsEnumerable().Contains(checkin.DateTime.DayOfWeek)
                    select checkin);
}

Enumerable.Contains(T)扩展方法将转换为数据库中的IN子句。

生成的查询将是这样的: SELECT [t0]。[Key],[t0]。[Day] FROM [Stuff] AS [t0] 在哪里[t0]。[日] IN(@ p0,@ p1)