我有一个使用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客户端为什么抛出错误吗?
答案 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 。