pri*_*mus 6 sqlite android ios mvvmcross xamarin
在我们的Android和iOS MVVMCross应用程序中,我们偶尔会遇到SQLiteException:繁忙的异常.
鉴于下面的代码,我们有几个存储库,每个存储库构造一个下面的实例和一个与Sqlite数据库的关联连接.想象一下,我们有一个Stocks Repository和一个Valuations Repository,将创建两个SqliteDataService实例:SqliteDataService类型为Stocks,SqliteDataService类型为Valuations,每个实例都与Sqlite数据库有连接.
存储库上的操作可以在后台线程上运行,这意味着我们可能会尝试在与Valuations同时将Stocks插入数据库.
现在,每个存储库创建自己的SqliteDataService,connectionObject锁将仅保护相同的存储库类型同时访问数据库,而不是保护Stocks和Valuations同时访问数据库.
我的问题是:
每个存储库创建连接是否有效,如果是,我们如何防范SqliteException:busy?
有更好的模式吗?即我们应该创建一个跨线程共享相同连接的非泛型SqliteDataService类吗?我们尝试了这个,但在Android上我们遇到了致命的例外.
Xamarin MVVMCross有没有一个坚实的Sqlite DAL模式?
public class SqliteDataService<T> : IDataService<T> where T : new()
{
private static object lockObject = new object();
private static object connectionObject = new object();
private static ISQLiteConnection _connection;
private static SqliteDataService<T> _instance;
public SqliteDataService(ISQLiteConnectionFactory connectionFactory, string dbPath)
{
if (_connection == null)
{
_connection = connectionFactory.Create (dbPath);
_connection.CreateTable<T> ();
}
}
public static SqliteDataService<T> GetInstance(ISQLiteConnectionFactory connectionFactory, string dbPath)
{
if (_instance == null)
{
lock (lockObject)
{
_instance = new SqliteDataService<T> (connectionFactory, dbPath);
}
}
return _instance;
}
public void CreateTable<T> ()
{
}
public void Insert(T value)
{
lock (connectionObject) {
_connection.Insert (value, typeof(T));
}
}
public void InsertAll(IEnumerable<T> values)
{
lock (connectionObject) {
_connection.Insert (values, typeof(T));
}
}
public IEnumerable<T> Read(Expression<Func<T, bool>> predicate)
{
lock (connectionObject) {
return _connection.Table<T> ().Where (predicate);
}
}
public T ReadFirst(Expression<Func<T, bool>> predicate)
{
lock (connectionObject) {
return Read (predicate).FirstOrDefault ();
}
}
public void Update(T value)
{
lock (connectionObject) {
_connection.Update (value, typeof(T));
}
}
public void Delete(Expression<Func<T, bool>> predicate)
{
lock (connectionObject) {
var valuesToDelete = Read (predicate);
if (valuesToDelete == null)
return;
foreach (var value in valuesToDelete) {
_connection.Delete (value);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 0
听起来你有几个选择:
仅实例化一个 SqliteDataService 并将对其的引用传递给您的 Stocks 和 Valuations 对象,这似乎是最明智的,因为两者都在同一个数据库上运行
实例化一个对象以用作服务外部的锁,并将引用传递到 SqliteDataService 构造函数中,以便两个服务共享该锁。我相信这会起作用,但我不是锁定方面的专家。
您可以在 try catch 块中处理 Busy 异常,并迭代计数器以对数据库进行最大次数的尝试,每次等待很短的时间,以便您有很好的连接机会。如果数据库仍然繁忙,您仍然会遇到异常,并且这个解决方案非常混乱。
重组数据库,使两个区域分开,这可能是不可能的,但值得考虑。
归档时间: |
|
查看次数: |
625 次 |
最近记录: |