我对移动和异步数据访问相对较新,我正在尝试使用Xamarin启动器和#34;跨平台"来构建业务线应用程序。 VS2017中的模板。似乎当我经常进行数据库操作时,我得到了数据库被锁定的情况。 (大多数问题涉及自己的sqlite实现)。我添加了非常详细的日志记录(我必须支持非技术端移动用户)。
我更改为(如其他答案中所建议的)用于数据库访问的单例模型,该模型在调用table.ReadAsync(见下文)时产生不可跟踪(意味着没有异常被捕获且没有xamarin日志条目)异常。
作为第二个问题,花了很多时间在这上面并遇到了许多不同的障碍(毫无疑问是我自己制造的)我想知道我是否没有遵循一些不言而喻的移动开发规则例如"每页只读取一个异步对象,并为100%异步"设计UI。我想做太多吗?这是我现在的"单身"数据访问类:
public static class MainDataStore
{
private static ReaderWriterLockSlim ReadLock = new ReaderWriterLockSlim();
public static bool IsInitialized { get; set; }
public static MobileServiceClient MobileService { get; set; }
public static bool UseAuthentication = true;
public static IMobileServiceSyncTable<User> UserTable;
public static IMobileServiceSyncTable<Showroom> ShowroomTable;
public static IEnumerable<User> Users { get; set; } //= new ObservableRangeCollection<User>();
public static IEnumerable<Showroom> Showrooms { get; set; }
public static void InitializeAsync()
{
try
{
if (IsInitialized)
return;
Logging.D("Starting to initialize main store.");
AuthenticationHandler handler = null;
handler = new AuthenticationHandler();
MobileService = new MobileServiceClient(App.AzureMobileAppUrl, handler)
{
SerializerSettings = new MobileServiceJsonSerializerSettings
{
CamelCasePropertyNames = true
}
};
var store = new MobileServiceSQLiteStore(Settings.DatabaseName);
store.DefineTable<User>();
store.DefineTable<Showroom>();
MobileService.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());
UserTable = MobileService.GetSyncTable<User>();
ShowroomTable = MobileService.GetSyncTable<Showroom>();
Logging.D("Finished initializing main store.");
IsInitialized = true;
}
catch (Exception ex)
{
Logging.E(ex); // Debug.WriteLine("EXCEPTION: " + ex.Message + ". Stack: " + ex.StackTrace);
}
}
public static async void Load(ECarnavalObjectType type)
{
Logging.D("Reading lock entering. Read count: " + ReadLock.CurrentReadCount.ToString());
// ReadLock.EnterReadLock();
switch (type)
{
case ECarnavalObjectType.Users:
await GetUsersAsync();
Users = await UserTable.ToEnumerableAsync();
break;
case ECarnavalObjectType.Showrooms:
await GetShowroomsAsync();
Showrooms = await ShowroomTable.ToEnumerableAsync();
break;
}
// ReadLock.ExitReadLock();
}
public static async Task GetUsersAsync()
{
if (CrossConnectivity.Current.IsConnected)
{
try
{
// await UserTable.ReadAsync<User>(UserTable.CreateQuery());
await UserTable.PullAsync($"all{typeof(User).Name}", UserTable.CreateQuery());
}
catch (Exception ex)
{
}
}
}
public static async Task GetShowroomsAsync()
{
await ShowroomTable.ReadAsync<Showroom>(ShowroomTable.CreateQuery());
}
}
答案 0 :(得分:0)
在您的代码中,您不必等待InitializeAsync(),这意味着您可能在同步数据库时仍将其锁定并建立数据库。
以单例形式排列代码,然后让每个单独的方法(读取/列表/等)调用await InitializeAsync()
来初始化数据库。如果已经创建了数据库,请尽早返回InitializeAsync()
方法(在那里有一些不错的代码)。
有关更多信息,请参阅我的书:https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter3/client/