'数据库被锁定'在xamarin项目

时间:2017-06-25 23:58:08

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

我对移动和异步数据访问相对较新,我正在尝试使用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());
    }
}

1 个答案:

答案 0 :(得分:0)

在您的代码中,您不必等待InitializeAsync(),这意味着您可能在同步数据库时仍将其锁定并建立数据库。

以单例形式排列代码,然后让每个单独的方法(读取/列表/等)调用await InitializeAsync()来初始化数据库。如果已经创建了数据库,请尽早返回InitializeAsync()方法(在那里有一些不错的代码)。

有关更多信息,请参阅我的书:https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter3/client/