没有为Xamarin MobileServiceClient PullAsync格式化DateTimes

时间:2018-05-01 16:24:48

标签: sqlite xamarin

我正在尝试与通过Visual Studio中的模板生成的Xamarin应用程序进行脱机同步。在我添加DateTime字段之前,同步一直有效。 Xamarin代码或Sqlite似乎错误地解释了DateTime。这肯定是正确解释从服务器发送的DateTime值的问题,但如何解决?我是Xamarin和Sqlite的新手,所以我很困惑这个问题。该问题发生在

await ClientServiceManager.ClientServiceManagerDefault.InspectionsTable.PullAsync("allInspections", _inspectionsTable.CreateQuery()); 

正在运行,但由于这已隐藏在类库中,因此我无法进行调试。

数据库中的数据看起来没问题(例如,参见突出显示的CreatedDate): Server Database

Fiddler报告以下json发送到移动应用程序:

enter image description here

数据存储区生成的Sqllite数据库表如下所示: enter image description here

同步后,如果您尝试使用select id, createddate from inspection查询数据,则无法在Sqlite数据库中读取数据:

System.FormatException: String was not recognized as a valid DateTime.

如果我运行查询select id, cast(createddate as text) from inspection,则为createddate显示的结果值为1525165956.457。

通过调用下面的PullAsync来触发同步:

    public class ClientServiceManager
{
    IMobileServiceSyncTable<InspectionItem> _inspectionItemsTable;
    IMobileServiceSyncTable<Inspection> _inspectionsTable;
    MobileServiceClient _client;

    public MobileServiceClient CurrentClient
    {
        get { return _client; }
    }

    public static ClientServiceManager ClientServiceManagerDefault { get; set; } = new ClientServiceManager();

    public IMobileServiceSyncTable<InspectionItem> InspectionItemsTable
    {
        get { return _inspectionItemsTable; }
    }

    public IMobileServiceSyncTable<Inspection> InspectionsTable
    {
        get { return _inspectionsTable; }
    }

    public ClientServiceManager()
    {
        _client = new MobileServiceClient(App.AzureMobileAppUrl)
        {
            SerializerSettings = new MobileServiceJsonSerializerSettings
            {
                CamelCasePropertyNames = true
            }
        };

        var path = Path.Combine(MobileServiceClient.DefaultDatabasePath, "syncstore.db");
        var store = new MobileServiceSQLiteStore(path);

        store.DefineTable<Inspection>();
        store.DefineTable<InspectionItem>();

        _client.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

        _inspectionItemsTable = _client.GetSyncTable<InspectionItem>();
        _inspectionsTable = _client.GetSyncTable<Inspection>();
    }

    public async Task<bool> SyncAsync()
    {
        try
        {
            Debug.WriteLine($"SyncAsync called. Need to sync {_client.SyncContext.PendingOperations} changes.");

            //Pull server table changes to local tables.
            await ClientServiceManager.ClientServiceManagerDefault.InspectionsTable.PullAsync("allInspections", _inspectionsTable.CreateQuery());
            await ClientServiceManager.ClientServiceManagerDefault.InspectionItemsTable.PullAsync("allInspectionItems", _inspectionItemsTable.CreateQuery());

            //Push all context changes to the server.
            await _client.SyncContext.PushAsync();
        }
        catch (MobileServicePushFailedException exc)
        {
            Debug.WriteLine($"MobileServicePushFailedException occurred.  Inner exception: {exc.InnerException}");

            if (exc.PushResult == null)
            {
                Debug.WriteLine($"Unable to sync, which is alright since we have offline capabilities: {exc.Message}");

                return false;
            }
            foreach (var error in exc.PushResult.Errors)
            {
                if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
                {
                    //Update failed, reverting to server's copy.
                    await error.CancelAndUpdateItemAsync(error.Result);
                }
                else
                {
                    // Discard local change.
                    await error.CancelAndDiscardItemAsync();
                }

                Debug.WriteLine($"Error executing sync operation. Item: {error.TableName} ({error.Item["id"]}). Operation discarded.");
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Unable to sync items: {ex.Message}");
            return false;
        }

        return true;
    }
}

此外,实体表基于此类,您可以在其中看到使用的数据类型:

using System;

#if SERVICE
using Microsoft.Azure.Mobile.Server.Tables;
#endif

namespace Abc.Base.Models
{
    // The model class files are shared between the mobile and service projects.
    public abstract class EntityData
#if SERVICE
        : ITableData
#endif
    {
        #region ITableData Properties

        public string Id { get; set; }
#if SERVICE
        public DateTimeOffset? CreatedAt { get; set; } = DateTimeOffset.Now;

        public DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.Now;

        public bool Deleted { get; set; }

        public byte[] Version { get; set; }
#endif
        #endregion

        public DateTime? CreatedDate { get; set; }

        public DateTime? UpdatedDate { get; set; }
    }
}

1 个答案:

答案 0 :(得分:0)

事实证明,pullasync工作正常。我一直使用Visual Studio插件&#34; SQLite / SQL Server Compact Toolbox检查SQLite表,并在尝试使用DateTimeOffset值呈现DateTime列时抛出错误。我为SQLite安装了数据库浏览器&#34; (http://sqlitebrowser.org/)并且在检查表时可以看到DateTimeOffset值,尽管它们被渲染为数字,而不是漂亮的日期和时间。