与Azure移动应用程序脱机同步无法正常工作,数据库看起来为空

时间:2017-08-30 14:50:43

标签: xamarin xamarin.forms azure-mobile-services

我正在尝试使用Azure移动应用程序实现脱机数据库同步。当我使用远程版本(使用MobileServiceClient.GetTable而不是MobileService.GetSyncTable)时,一切正常。但是,我无法使用本地SQLite数据库。

DatabaseContext类在Autofac容器中注册为单例。

public class DatabaseContext
{
    private readonly MobileServiceClient _client;
    private readonly MobileServiceSQLiteStore _store;

    public DatabaseContext()
    {
        if (File.Exists(Constants.LocalDatabase))
        {
            File.Delete(Constants.LocalDatabase);
        }

        _client = new MobileServiceClient(Constants.ApiEndpoint);
        _store = new MobileServiceSQLiteStore(Constants.LocalDatabaseName);
    }

    public async Task Initialize()
    {
        _store.DefineTable<Activities>();

        await _client.SyncContext.InitializeAsync(_store);
        await _client.SyncContext.PushAsync();

        var activitiesTable = _client.GetSyncTable<Activities>();
        await activitiesTable.PullAsync(null, activitiesTable.CreateQuery());


        // DATA IS EMPTY
        var data = await activitiesTable.CreateQuery().ToListAsync();
    }
}

我的模特课:

public class Activities
{
    public Guid Id { get; set; }
    public string Name{ get; set; }
    public DateTimeOffset? UpdatedAt { get; set; }
    public DateTimeOffset? CreatedAt { get; set; }
    public byte[] Version { get; set; }
}

当我在azure仪表板中查看我的流媒体日志时,我可以看到此请求:

GET /tables/Activities $skip=0&$top=50&__includeDeleted=true&$skip=0&$top=50&__includeDeleted=true&X-ARR-LOG-ID=19cd669b-df9a-41ee-b86e-9db766fc8e01 443 - 70.52.250.32 ZUMO/4.0+(lang=Managed;+os=Android;+os_version=6.0.1;+arch=Unix;+version=4.0.0.0) - 200 0 0 3228 1241 2160

使用Postman调用它返回数据。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

虽然你的Activities模型可能有用,但我会按如下方式定义我的模型:

public class Activities
{
    public string Id { get; set; }
    public string Name { get; set; }
    [UpdatedAt]
    public DateTimeOffset? UpdatedAt { get; set; }
    [CreatedAt]
    public DateTimeOffset? CreatedAt { get; set; }
    [Version]
    public byte[] Version { get; set; }
}

注意:数据库会更新createdAtupdatedAtversion字段,如果您将记录推送到服务器,它们将会填充。

我在我身边测试过,发现我可以从服务器中提取记录,并且我的sqlite数据库中有记录。

  

await activitiesTable.PullAsync(null,activitiesTable.CreateQuery());

以上代码会自动发送多个请求(单个请求的默认页面大小为50)来提取所有记录,然后执行以下sql语句来更新本地数据存储:

  

BEGIN TRANSACTION

     

INSERT或IGNORE INTO [TodoItem]([id])VALUES(@ p0),(@ p1),(@ p2),(@ p3),(@ p4),(@ p5),(@ p6) ,(@ P7),(@ P8),(@ P9),(@ P10),(@ P11),(@ P12),(@ P13),(@ P14),(@ P15),(@ P16) ,(@ P17),(@ P18),(@ P19),(@ P20),(@ P21),(@ P22),(@ P23),(@ P24),(@ P25),(@ P26) ,(@ P27),(@ P28),(@ P29),(@ P30),(@ P31),(@ P32),(@ P33),(@ P34),(@ P35),(@ P36) ,(@ P37),(@ P38),(@ P39),(@ P40),(@ P41),(@ P42),(@ P43),(@ P44),(@ P45),(@ P46) ,(@ P47),(P48 @),(@ P49)

     

UPDATE [TodoItem] SET [Text] = @ p0,[UserId] = @ p1 WHERE [id] = @ p2

     

UPDATE [TodoItem] SET [Text] = @ p0,[UserId] = @ p1 WHERE [id] = @ p2

     

     

     

COMMIT TRANSACTION

     

BEGIN TRANSACTION

     

INSERT或IGNORE INTO [__config]([id])VALUES(@ p0)

     

UPDATE [__config] SET [value] = @ p0 WHERE [id] = @ p1

     

COMMIT TRANSACTION

有关详细信息,请参阅Debugging the Offline Cache

根据您的描述,您可以从服务器检索数据,但无法更新本地sqlite数据库。我建议您在调用PullAsync时可以利用fiddler来捕获网络跟踪,并打开您的sqlite数据库来检查您的表。

此外,正如Using soft delete in Mobile Services所述:

  

使用Offline data Sync for Mobile Services功能时,客户端SDK会自动查询已删除的记录并将其从本地数据库中删除。如果未启用软删除,则需要在后端编写其他代码,以便客户端SDK知道要从本地存储中删除哪些记录。否则,客户端本地存储和后端将与这些已删除的记录不一致,并且必须调用客户端方法PurgeAsync()以清除本地存储。

注意:您需要在致电deleted时查看记录中的PullAsync媒体资源。

此外,您可以利用移动应用下的“DEPLOYMENT&gt;快速入门”下载并运行Xamarin.Forms解决方案来缩小此问题。有关详细信息,请参阅here。另外,你可以参考adrian hall的关于Chapter 3 - Data Access and Offline Sync的书。

答案 1 :(得分:2)

问题来自API方面。我能够使用Postman检索记录,但是id字段不是小写的。

[Key]
[TableColumn(TableColumnType.Id)]
public string Id { get; set; }

应该是:

[Key]
[TableColumn(TableColumnType.Id)]
public string id { get; set; }

非常令人沮丧的错误。

鉴于本教程:https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter3/server/,由于&#34; Id&#34;这个类无法正常工作。田野是骆驼案。

namespace Chapter3.DataObjects
{
    public class Example : EntityData
    {
        public string StringField { get; set; }
        public int IntField { get; set; }
        public double DoubleField { get; set; }
        public DateTimeOffset DateTimeField { get; set; }
    }
}

EntityData类将使用远程表(MobileClientService.GetTable<T>),但不能使用同步表(MobileClientService.GetSyncTable<T>)。