我正在使用Azure与Xamarin.Forms一起创建一个离线的移动应用程序。
我的解决方案是基于https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter3/client/的
下面是用于脱机同步的代码:
public class AzureDataSource
{
private async Task InitializeAsync()
{
// Short circuit - local database is already initialized
if (client.SyncContext.IsInitialized)
{
return;
}
// Define the database schema
store.DefineTable<ArrayElement>();
store.DefineTable<InputAnswer>();
//Same thing with 16 others table
...
// Actually create the store and update the schema
await client.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());
}
public async Task SyncOfflineCacheAsync()
{
await InitializeAsync();
//Check if authenticated
if (client.CurrentUser != null)
{
// Push the Operations Queue to the mobile backend
await client.SyncContext.PushAsync();
// Pull each sync table
var arrayTable = await GetTableAsync<ArrayElement>();
await arrayTable.PullAsync();
var inputAnswerInstanceTable = await GetTableAsync<InputAnswer>();
await inputAnswerInstanceTable.PullAsync();
//Same thing with 16 others table
...
}
}
public async Task<IGenericTable<T>> GetTableAsync<T>() where T : TableData
{
await InitializeAsync();
return new AzureCloudTable<T>(client);
}
}
public class AzureCloudTable<T>
{
public AzureCloudTable(MobileServiceClient client)
{
this.client = client;
this.table = client.GetSyncTable<T>();
}
public async Task PullAsync()
{
//Query name used for incremental pull
string queryName = $"incsync_{typeof(T).Name}";
await table.PullAsync(queryName, table.CreateQuery());
}
}问题是,即使没有任何东西可做,同步也要花费很长时间( Android设备上需要8-9秒,整个数据库需要超过25秒)。
我查看了费德勒,以找出移动应用程序BackEnd响应所需的时间,每个请求大约需要50毫秒,所以问题似乎不是从这里来的。
有人也有同样的麻烦吗?有什么地方是我做错或提示,以提高我的同步性能?
发布于 2018-05-31 01:43:25
我们的特定问题与我们的数据库迁移有关。数据库中的每一行都具有相同的updatedAt值。我们运行了一个SQL脚本来修改它们,使它们都是唯一的。
这个修复实际上是因为一些其他的问题,在这个问题上,并不是所有的行都因为某种未知的原因而被返回,但是我们也看到了一个很大的速度改进。
另外,另一个改进加载时间的奇怪修复方法如下所示。
在我们第一次提取所有数据之后(这是可以理解的,需要一些时间)--我们在返回的一个行上做了一个UpdateAsync(),之后我们没有按它。
我们已经了解到离线同步的工作方式是,它将提取任何有日期更新的,而不是最近更新的。与此相关的是一小部分速度的提高。
最后,我们为提高速度所做的最后一件事是,如果数据已经在视图中缓存了一个副本,就不会再次获取数据。不过,这对您的用例可能不起作用。
public List<Foo> fooList = new List<Foo>
public void DisplayAllFoo()
{
if(fooList.Count == 0)
fooList = await SyncClass.GetAllFoo();
foreach(var foo in fooList)
{
Console.WriteLine(foo.bar);
}
}编辑2019年3月20日:随着这些改进的到位,我们仍然看到非常缓慢的同步操作,使用的方式与OP中提到的相同,还包括我在这里的答案中列出的改进。
我鼓励大家就如何提高这一速度分享他们的解决办法或想法。
发布于 2020-04-05 02:12:34
拉()慢的原因之一是(10)行得到相同的UpdatedAt值。当您同时更新行时会发生这种情况,例如运行SQL命令。
克服这种情况的一种方法是修改表上的默认触发器。为了确保每一行都得到一个唯一的UpdateAt,我们执行了如下操作:
ALTER TRIGGER [dbo].[TR_dbo_Items_InsertUpdateDelete] ON [dbo].[TableName]
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
DECLARE @InsertedAndDeleted TABLE
(
Id NVARCHAR(128)
);
DECLARE @Count INT,
@Id NVARCHAR(128);
INSERT INTO @InsertedAndDeleted
SELECT Id
FROM inserted;
INSERT INTO @InsertedAndDeleted
SELECT Id
FROM deleted
WHERE Id NOT IN
(
SELECT Id
FROM @InsertedAndDeleted
);
--select * from @InsertedAndDeleted;
SELECT @Count = Count(*)
FROM @InsertedAndDeleted;
-- ************************ UpdatedAt ************************
-- while loop
WHILE @Count > 0
BEGIN
-- selecting
SELECT TOP (1) @Id = Id
FROM @InsertedAndDeleted;
-- updating
UPDATE [dbo].[TableName]
SET UpdatedAt = Convert(DATETIMEOFFSET, DateAdd(MILLISECOND, @Count, SysUtcDateTime()))
WHERE Id = @Id;
-- deleting
DELETE FROM @InsertedAndDeleted
WHERE id = @Id;
-- counter
SET @Count = @Count - 1;
END;
END;https://stackoverflow.com/questions/48259872
复制相似问题