Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/216.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android SQLite数据库在读取时锁定_Android_Sqlite_Xamarin_Xamarin.android_Sqlite Net Pcl - Fatal编程技术网

Android SQLite数据库在读取时锁定

Android SQLite数据库在读取时锁定,android,sqlite,xamarin,xamarin.android,sqlite-net-pcl,Android,Sqlite,Xamarin,Xamarin.android,Sqlite Net Pcl,我们正在构建的Xamarin.Android应用程序存在数据库锁定问题。作为应用程序功能的概述: 表A中的get插入项 用户按下按钮运行计划作业,以将数据从数据库同步到API。当成功响应返回时,我们将删除表中的该行 用户仍然可以将数据添加到表A中,作为其例程的一部分 我们在A表有锁 我们构建了一个测试应用程序来尝试和模拟这一点,解决方案是构建一个表B来复制表a中的数据,这样用户就可以继续处理表a。但是,当表B中的数据试图同步(删除就是为了模拟这一点)其数据时,我们会在Get()上获得表上的锁

我们正在构建的Xamarin.Android应用程序存在数据库锁定问题。作为应用程序功能的概述:

  • 表A中的get插入项
  • 用户按下按钮运行计划作业,以将数据从数据库同步到API。当成功响应返回时,我们将删除表中的该行
  • 用户仍然可以将数据添加到表A中,作为其例程的一部分
  • 我们在A表有锁
我们构建了一个测试应用程序来尝试和模拟这一点,解决方案是构建一个表B来复制表a中的数据,这样用户就可以继续处理表a。但是,当表B中的数据试图同步(删除就是为了模拟这一点)其数据时,我们会在Get()上获得表上的锁

我的数据库代码如下:

使用系统;
使用SQLite;
使用System.Collections.Generic;
使用System.Linq;
名称空间锁模拟
{
公共类样本数据库B:IDatabase
{
公共样本数据库B()
{
尝试
{
字符串dbPath=System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
“样本B.db3”);
使用(SQLiteConnection db=newsqliteconnection(dbPath))
{
db.CreateTable();
db.Close();
}
}
捕获(例外情况除外)
{
Console.WriteLine(“已创建数据库”);
}
}
公共列表Get()
{
列表样本=新列表();
字符串dbPath=System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
“样本B.db3”);
使用(var db=new SQLiteConnection(dbPath,SQLiteOpenFlags.ReadOnly))
{
var s=db.Table();
//问题在这里>s.ToList()显示锁
样本=s.ToList();
db.Close();
}
返回样品;
}
公开作废副本(列出样本)
{
字符串dbPath=System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
“样本B.db3”);
使用(var db=new SQLiteConnection(dbPath,SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.FullMutex | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache))
{
db.InsertAll(样本);
db.Close();
}
}
公共作废保存(对象示例)
{
字符串dbPath=System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
“样本B.db3”);
使用(var db=new SQLiteConnection(dbPath,SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache))
{
db.插入(样本);
db.Close();
}
}
}
}
我的预定工作在这里:

使用系统;
使用System.Collections.Generic;
使用System.Threading.Tasks;
使用Android.App;
使用Android.App.Job;
名称空间锁模拟
{
[Service(Name=“com.testapp.LockSimulation.Job”,Permission=“android.Permission.BIND\u Job\u Service”)]
公共类同步作业:作业服务
{
SampleDatabaseB db=null;
公共覆盖bool OnStartJob(JobParameters jobParams)
{
db=新的SampleDatabaseB();
Task.Run(()=>
{
var loopCount=jobParams.Extras.GetInt(“loopCount”,10);
List samples=db.Get();
尝试
{
foreach(样本中的样本)
{
db.删除(样本);
}
如果(db.Get().Count==0)
{
JobFinished(jobParams,false);
}
其他的
{
JobFinished(jobParams,true);
}
}
catch(SQLite.SQLiteException-ex)
{
控制台写入线(ex);
}
});
返回true;
}
公共覆盖bool OnStopJob(JobParameters jobParams)
{
//在作业尝试完成之前,我们将检查示例数据库。
//如果数据库中有样本,我们需要告知流程
//重新运行作业。
//如果执行此操作时出现问题,请告诉流程重试。
//如果(db.Get().Count==0)
//{
//返回false;
//}
//否则
//{
//返回true;
//}
尝试
{
如果(db.Get().Count==0)
{
返回false;
}
其他的
{
返回true;
}
}
捕获(例外情况除外)
{
var属性=新字典
{
{“同步作业异常”,例如Message},
{“DB问题”,“DB可能正在对其进行处理。将重试。”}
};
Console.WriteLine(属性);
//崩溃。跟踪错误(例如,属性);
返回true;
}
}
}
}
我的按钮代码如下:

button.Click+=委托{
SampleDatabaseB SampleDatabaseB=新的SampleDatabaseB();
List samplesA=sampleDatabase.Get();
List samplesB=sampleDatabaseB.Get();
WriteLine(String.Format(“拷贝{0}之前的总样本数”,samplesA.Count));
WriteLine(String.Format(“复制{0}之前B中的总样本数”,samplesB.Count));
样本数据库B.副本(样本A);
sampleDatabase.DeleteAll();
WriteLine(String.Format(“复制{0}后B中的样本总数”,sampleDatabaseB.Get().Count));
WriteLine(String.Format(“After副本{0},sampleDatabase.Get().Count中的样本总数”);
var jobBuilder=this.createJobbuilderUserSingJobId(1)
using System;
using SQLite;
using System.Collections.Generic;
using System.Linq;

namespace LockSimulation
{
    public class SampleDatabaseB : IDatabase
    {
        public SampleDatabaseB()
        {
        try
        {
            string dbPath = System.IO.Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Personal),
                "sampleb.db3");

            using (SQLiteConnection db = new SQLiteConnection(dbPath))
            {
                db.CreateTable<Sample>();
                db.Close();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("DB already created");
        }

    }


    public List<Sample> Get()
    {
        List<Sample> samples = new List<Sample>();
        string dbPath = System.IO.Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Personal),
                "sampleb.db3");

        using (var db = new SQLiteConnection(dbPath,SQLiteOpenFlags.ReadOnly))
        {

            var s = db.Table<Sample>();

            // ISSUE IS HERE> s.ToList() SHOWS THE LOCK

            samples = s.ToList();
            db.Close();

        }
        return samples;
    }

    public void Copy(List<Sample> samples)
    {
        string dbPath = System.IO.Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Personal),
                "sampleb.db3");

        using (var db = new SQLiteConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.FullMutex | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache))
        {
            db.InsertAll(samples);
            db.Close();
        }
    }

    public void Save(object sample)
    {
        string dbPath = System.IO.Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Personal),
                "sampleb.db3");

        using (var db = new SQLiteConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache))
        {
            db.Insert(sample);
            db.Close();
        }
    }
  }
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Android.App;
using Android.App.Job;

namespace LockSimulation
{
    [Service(Name = "com.testapp.LockSimulation.Job", Permission = "android.permission.BIND_JOB_SERVICE")]
public class SyncJob : JobService
{
    SampleDatabaseB db = null;

    public override bool OnStartJob(JobParameters jobParams)
    {
        db = new SampleDatabaseB();
        Task.Run( () =>
        {
            var loopCount = jobParams.Extras.GetInt("LoopCount", 10);
            List<Sample> samples = db.Get();
            try
            {
                foreach (Sample sample in samples)
                {
                    db.Delete(sample);
                }

                if (db.Get().Count == 0)
                {
                    JobFinished(jobParams, false);
                }
                else
                {
                    JobFinished(jobParams, true);
                }
            }
            catch (SQLite.SQLiteException ex)
            {
                Console.WriteLine(ex);
            }
        });

        return true;
    }

    public override bool OnStopJob(JobParameters jobParams)
    {
        //Before the Job tries to finish, we will check the Samples DB.
        //If there is Samples on the DB, we will need to tell the process 
        //to run the job again.
        //If there is an issues in doing so, tell the process to try again.

        //if (db.Get().Count == 0)
        //{
        //    return false;
        //}
        //else
        //{
        //    return true;
        //}

        try
        {
            if (db.Get().Count == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        catch (Exception ex)
        {
            var properties = new Dictionary<string, string>
            {
                { "Syncing Job Exception", ex.Message},
                { "DB Issue", "DB could be having processing done on it. Will try again."}
            };
            Console.WriteLine(properties);
            //Crashes.TrackError(ex, properties);
            return true;
        }
    }
}
}
button.Click += delegate {
            SampleDatabaseB sampleDatabaseB = new SampleDatabaseB();

            List<Sample> samplesA = sampleDatabase.Get();
            List<Sample> samplesB = sampleDatabaseB.Get();

            Console.WriteLine(String.Format("Total Samples In A Before Copy {0}", samplesA.Count));
            Console.WriteLine(String.Format("Total Samples In B Before Copy {0}", samplesB.Count));

            sampleDatabaseB.Copy(samplesA);
            sampleDatabase.DeleteAll();

            Console.WriteLine(String.Format("Total Samples In B After Copy {0}", sampleDatabaseB.Get().Count));

            Console.WriteLine(String.Format("Total Samples In A After Copy {0}", sampleDatabase.Get().Count));


            var jobBuilder = this.CreateJobBuilderUsingJobId<SyncJob>(1)
                                     .SetRequiredNetworkType(NetworkType.Any)
                                     .SetBackoffCriteria(2000, BackoffPolicy.Linear)
                                     .SetPersisted(true)
                                     .Build();

            var jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
            var scheduleResult = jobScheduler.Schedule(jobBuilder);

            if (JobScheduler.ResultSuccess == scheduleResult)
            {
                Console.WriteLine("Samples Scheduled for Syncing Successfully");
            }
            else
            {
                Console.WriteLine("Samples Unsuccessfully Scheduled for Syncing.");
            }
        };