Azure IMobileServiceSyncTable解析器堆栈溢出

时间:2018-07-08 23:08:42

标签: sqlite azure xamarin azure-mobile-services

我有一个使用Azure Mobile脱机同步的应用程序。我正在尝试使用以下查询iMobileServiceSyncTable:

var listOfIds = dataItems.Select(i => i.Id).ToList();

IEnumerable<DataItemValue> items = await dataItemValueTable
                .Where(i => listOfIds.Contains(i.DataItemId))
                .ToEnumerableAsync();

如果listOfIds中的项目数量很少,则一切正常。如果更大,例如180,然后出现错误:

Exception thrown: 'Microsoft.WindowsAzure.MobileServices.SQLiteStore.SQLiteException' in System.Private.CoreLib.dll
Error executing SQLite command: 'parser stack overflow'.:GetDataItemValues::Sync error: {0}

它应该等效于“ SELECT * FROM tablename WHERE Id IN('a','b','c'...)”,但是“ IN”语句中的180个值似乎很低,导致问题?如果我将DB Browser用于SQLite并手动进行查询,那么它将毫无问题。

您知道Azure MobileServices客户端为什么抛出错误吗?

1 个答案:

答案 0 :(得分:1)

  

它应该等效于“ SELECT * FROM tablename WHERE Id IN('a','b','c'...)”,但是“ IN”语句中的180个值似乎很低,导致问题?

Debugging the Offline Cache之后并覆盖方法ExecuteQueryInternal,然后您会发现生成的SQL语句如下所示:

  

选择*从[城市]哪里(((((([[id] = @ p1)OR([id] = @ p2))或([id] = @ p3))OR([[id] = @ p4 ))OR([[id] = @ p5))

我不知道您用于查询的Id的格式或长度。您需要对它进行测试,并根据Id获得适当的计数,然后将listOfIds除以并批量执行查询以检索记录。该代码段如下所示:

var listOfIds = dataItems.Select(i => i.Id).ToList();
List<DataItemValue> items= new List<DataItemValue>();
int batchSize = 50;
for (int i = 0; i < Math.Ceiling((double)listOfIds.Count / batchSize); i++)
{
    var ids = listOfIds.Skip(i * batchSize).Take(batchSize);
    var results = await cityTable.Where(c => ids.Contains(c.Id)).ToEnumerableAsync();
    if (results != null)
        items.AddRange(results);
}
  

您知道Azure MobileServices客户端为什么抛出错误吗?

     

引发的异常:System.Private.CoreLib.dll中的“ Microsoft.WindowsAzure.MobileServices.SQLiteStore.SQLiteException”   执行SQLite命令时出错:'解析器堆栈溢出'.: GetDataItemValues :: Sync错误:{0}

SDK将在MobileServiceSQLiteStore.cs下内部调用ExecuteQueryInternal,我假设生成的SQL语句可能会命中Limits In SQLite

  

表达式树的最大深度

     

SQLite将表达式解析为树以进行处理。在代码生成期间,SQLite递归地遍历此树。 因此,表达式树的深度受到限制,以避免使用过多的堆栈空间

     

SQLITE_MAX_EXPR_DEPTH参数确定最大表达式树深度。如果该值为0,则不强制执行任何限制。 当前实现的默认值为1000