IMobileServiceSyncTable.Where过滤器无法正常工作?

时间:2014-09-11 18:40:03

标签: sqlite azure-mobile-services

更新:如果我使用"f40a0cad-608c-4190-a79e-47af918c087a"对Where过滤器进行硬编码,它会返回用户,看起来其他字符串字段(如Name或FacebookToken)即使在硬编码时也不起作用。

我正在使用 WindowsAzure.MobileServices 1.3.0-alpha3 WindowsAzure.MobileServices.SQLiteStore 1.0.0-alpha3

之前我已经多次这样做了没有任何问题,但是我遇到了一个奇怪的问题,当我知道它在表格中的事实时,我的过滤器没有返回任何内容。这是我的代码:

public async Task SyncUserAsync(string facebookToken)
{
    await _userTable.PullAsync ();
    var user = (await _userTable.Where(x => x.FacebookToken == facebookToken)
                                .Take (1)
                                .ToEnumerableAsync ())
                                .FirstOrDefault ();
    var userTwo = await _userTable.LookupAsync ("f40a0cad-608c-4190-a79e-47af918c087a");
    if (user != null)
        Debug.WriteLine ("Facebook user {0} is synced", facebookToken);
}

此代码导致null user,但userTwo查找返回我正在寻找的用户。即使我从FacebookToken复制userTwo并对Where过滤器进行硬编码,也会返回null。

1 个答案:

答案 0 :(得分:0)

LookupAsync方法根据对象的 id 进行查询。如果要使两个调用(ToEnumerable和Lookup)等效,则需要按如下方式重写它们:

public async Task SyncUserAsync(string facebookToken)
{
    await _userTable.PullAsync ();
    var facebookToken = "f40a0cad-608c-4190-a79e-47af918c087a";
    var user = (await _userTable.Where(x => x.Id == facebookToken)
                                .Take (1)
                                .ToEnumerableAsync ())
                                .FirstOrDefault ();
    var userTwo = await _userTable.LookupAsync (facebookToken);
    if (user != null)
        Debug.WriteLine ("Facebook user {0} is synced", facebookToken);
}
评论后

更新

这是一个complete, self-contained, small(-ish) example,它遵循您所拥有的具体情况:

服务:

使用Facebook身份验证配置的移动服务,带有一个表(用户),带有以下插入脚本:

function insert(item, user, request) {
    item.facebookToken = user.userId;
    request.execute();
}

客户端:

Windows应用商店应用(也可能是其他平台)。添加了NuGet对最新版Azure Mobile Services SQLiteStore package(1.0.0-beta)的引用。

MainPage.xaml中:

带有两个按钮的空白应用程序:

<Page
    x:Class="App3.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App3"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button Name="btnPopulateRemote" Content="Populate remote table" Margin="10" FontSize="30"
                HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                Click="btnPopulateRemote_Click"/>
        <Button Name="btnPullAndSearch" Content="Pull and search locally" Margin="10" FontSize="30"
                HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="1"
                Click="btnPullAndSearch_Click"/>
        <TextBox Name="txtDebug" AcceptsReturn="True" Margin="10" Grid.Row="1" Grid.ColumnSpan="2"/>
    </Grid>
</Page>

MainPage.xaml.cs中:

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using Newtonsoft.Json;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace App3
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public static MobileServiceClient MobileService = new MobileServiceClient(
            "https://MOBILE-SERVICE-NAME.azure-mobile.net/",
            <<YOUR-APP-KEY-GOES-HERE>>
        );

        private const string TestId = "f40a0cad-608c-4190-a79e-47af918c087a";
        private string facebookToken;

        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void btnPopulateRemote_Click(object sender, RoutedEventArgs e)
        {
            await InitializeIfNecessary();
            Debug("Populating the remote table...");
            try
            {
                var table = MobileService.GetTable<User>();
                var user = new User
                {
                    Id = "f40a0cad-608c-4190-a79e-47af918c087a",
                    Name = "John Doe"
                };
                await table.InsertAsync(user);
                Debug("Inserted: {0}", user);

                user = new User
                {
                    Id = "01234567-89ab-cdef-0123-456789abcdef",
                    Name = "Jane Roe"
                };
                await table.InsertAsync(user);
                Debug("Inserted: {0}", user);
            }
            catch (Exception ex)
            {
                TraceError(ex);
            }

            Debug("");
        }

        private void TraceError(Exception ex)
        {
            Debug("Error: {0} - {1}", ex.GetType().Name, ex.Message);
            Exception inner = ex.InnerException;
            while (inner != null)
            {
                Debug("    {0} - {1}", inner.GetType().Name, inner.Message);
                inner = inner.InnerException;
            }
        }

        private async Task InitializeIfNecessary()
        {
            if (MobileService.CurrentUser == null)
            {
                await MobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook);
                Debug("Logged in as {0}", MobileService.CurrentUser.UserId);
                this.facebookToken = MobileService.CurrentUser.UserId;
                Debug("Using this value for the FacebookToken: {0}", this.facebookToken);
                Debug("");

                Debug("Creating the local store");
                var store = new MobileServiceSQLiteStore("file.db");
                store.DefineTable<User>();
                await MobileService.SyncContext.InitializeAsync(store);
                Debug("Initialized the sync context / local store");

                Debug("");
            }
        }

        private async void btnPullAndSearch_Click(object sender, RoutedEventArgs e)
        {
            await InitializeIfNecessary();
            Debug("Pulling data locally and searching...");
            try
            {
                var _usersTable = MobileService.GetSyncTable<User>();
                await _usersTable.PullAsync();
                Debug("Pulled data into local table");
                var itemsInLocalTable = (await _usersTable.ReadAsync()).Count();
                Debug("There are {0} items in the local table", itemsInLocalTable);

                var user = (await _usersTable.Where(x => x.FacebookToken == facebookToken)
                    .Take(1)
                    .ToEnumerableAsync())
                    .FirstOrDefault();
                Debug("User retrieved: {0}", user);

                var userTwo = await _usersTable.LookupAsync(TestId);
                Debug("User two: {0}", userTwo);
            }
            catch (Exception ex)
            {
                TraceError(ex);
            }

            Debug("");
        }

        private void Debug(string text, params object[] args)
        {
            if (args != null && args.Length > 0) text = string.Format(text, args);
            this.txtDebug.Text = this.txtDebug.Text + text + Environment.NewLine;
        }
    }

    public class User
    {
        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("facebookToken")]
        public string FacebookToken { get; set; }

        public override string ToString()
        {
            return string.Format("User[{0}, {1}, {2}]", Id, Name, FacebookToken);
        }
    }
}