sqlite-net-pcl 中的 InsertAll 和 UpdateAll VS SQLite.Net-PCL 中的 InsertOrReplaceAll
InsertAll & UpdateAll in sqlite-net-pcl VS InsertOrReplaceAll in SQLite.Net-PCL
我想删除SQLite.Net-PCL package and want to use sqlite-net-pcl因为我后来发现SQLite.Net-PCL
没有正式维护
我的 Xamarin 项目中有一些表将 GUID
存储为字符串类型的主键。我有来自服务器的记录列表,目前使用 InsertOrReplaceAll
方法根据我的 GUID
主键一次性插入新记录和更新现有记录。
现在,sqlite-net-pcl
没有 InsertOrReplaceAll
方法,而只有 InsertAll
和 UpdateAll
方法。 Microsoft msdn Link 表示检查主键是否具有可用值,并根据该值决定是否必须插入或更新记录。
但是,我遇到这样一种情况,在插入或更新对象之前,主键值总是预先设置在 List
中,并且不想循环检查记录是否存在超过 500 条记录。
在这种情况下如何一次插入或替换我的所有记录?
考虑以下示例来理解这种情况:
using (var conn = new DBConnectionService().GetConnection())
{
List<ENTEmployee> employees = new List<ENTEmployee>()
{
new ENTEmployee(){ Id = "b977ec04-3bd7-4691-b4eb-ef47ed6796fd", FullName = "AAA BBB", Salary = 15000 },
new ENTEmployee(){ Id = "c670a3e2-b13f-42b3-849c-fd792ebfd103", FullName = "BBB BBB", Salary = 16000 },
new ENTEmployee(){ Id = "d961c33c-0244-48dc-8e10-f4f012386eb6", FullName = "CCC BBB", Salary = 17000 },
new ENTEmployee(){ Id = "35be4508-ff93-4be8-983f-d4908bcc592d", FullName = "DDD BBB", Salary = 18000 },
new ENTEmployee(){ Id = "0875549c-d06c-4983-b89a-edf81b6aa70d", FullName = "EEE BBB", Salary = 19000 },
};
var insertResult = conn.InsertAll(employees);
//Updated Record
employees[0].FullName = "AAA Updated";
employees[0].Salary = 12300;
//New Records
employees.Add(new ENTEmployee() { Id = "87f48ecf-715c-4327-9ef3-11712ba4a120", FullName = "FFF BBB", Salary = 20000 });
employees.Add(new ENTEmployee() { Id = "85f53888-b1e9-460c-8d79-88010f143bcf", FullName = "GGG BBB", Salary = 21000 });
//Now here,
//How to decide which records to be inserted and which records to be updated for List employees?
}
How to Insert Or Replace all my records at once in this case?
有两种方法可以解决问题L:
遍历您的记录列表并对列表中的每个对象使用 conn.InsertOrReplace(object)
:
for(ENTEmployee emp in employees)
{
conn.InsertOrReplace(雇员);
}
使用Sql命令插入或替换记录(需要您构造命令字符串):
string cmd = @"insert or replace into employ(id,FullName,salary)
values('c670a3e2-b13f-42b3-849c-fd792ebfd103', 'fullname1',32),
('d961c33c-0244-48dc-8e10-f4f012386eb6', 'fullname2',23);";
conn.Execute(cmd);
我实现了一个与他们的实现类似的扩展方法。您可以将其与 SQLite.Net-PCL
project.
中的原始版本进行比较
static public class SQLiteConnectionExtensions
{
/// <summary>
/// Inserts all specified objects.
/// For each insertion, if a UNIQUE
/// constraint violation occurs with
/// some pre-existing object, this function
/// deletes the old object.
/// </summary>
/// <param name="objects">
/// An <see cref="IEnumerable" /> of the objects to insert or replace.
/// </param>
/// <returns>
/// The total number of rows modified.
/// </returns>
static public int InsertOrReplaceAll(this SQLiteConnection connection, IEnumerable objects, bool runInTransaction = true)
{
var c = 0;
if (objects == null)
return c;
if (runInTransaction)
{
connection.RunInTransaction(() =>
{
foreach (var r in objects)
{
c += connection.Insert(r, "OR REPLACE", Orm.GetType(r));
}
});
}
else
{
foreach (var r in objects)
{
c += connection.Insert(r, "OR REPLACE", Orm.GetType(r));
}
}
return c;
}
}
刚刚对 4 种不同的方式进行了基准测试来更新许多项目:
上下文:更新包含 5000 个项目的产品(每个对象有 7 个属性)数据库。
- 在 foreach 循环中使用 exists(通过 PK 上的 countasync)、insertasync 和 updateasync:大约 30
秒
- 使用 foreach 循环和 InsertOrReplaceAsync:大约 2 分钟
- 使用@Genfood 提出的扩展:大约 92 毫秒
- 使用@Elvis Xia 建议的手动查询 - MSFT:大约 81 毫秒
我刚刚对扩展进行了一些修改以管理异步方法的使用
public static class SqliteExtensions
{
static async public Task<int> InsertOrReplaceAll(this SQLiteAsyncConnection connection, IEnumerable objects, bool runInTransaction = true)
{
var c = 0;
if (objects == null)
return c;
if (runInTransaction)
{
await connection.RunInTransactionAsync(nonAsyncConnection =>
{
foreach (var r in objects)
{
c += nonAsyncConnection.Insert(r, "OR REPLACE", Orm.GetType(r));
}
});
}
else
{
foreach (var r in objects)
{
c += await connection.InsertAsync(r, "OR REPLACE", Orm.GetType(r));
}
}
return c;
}
}
我想删除SQLite.Net-PCL package and want to use sqlite-net-pcl因为我后来发现SQLite.Net-PCL
没有正式维护
我的 Xamarin 项目中有一些表将 GUID
存储为字符串类型的主键。我有来自服务器的记录列表,目前使用 InsertOrReplaceAll
方法根据我的 GUID
主键一次性插入新记录和更新现有记录。
现在,sqlite-net-pcl
没有 InsertOrReplaceAll
方法,而只有 InsertAll
和 UpdateAll
方法。 Microsoft msdn Link 表示检查主键是否具有可用值,并根据该值决定是否必须插入或更新记录。
但是,我遇到这样一种情况,在插入或更新对象之前,主键值总是预先设置在 List
中,并且不想循环检查记录是否存在超过 500 条记录。
在这种情况下如何一次插入或替换我的所有记录?
考虑以下示例来理解这种情况:
using (var conn = new DBConnectionService().GetConnection())
{
List<ENTEmployee> employees = new List<ENTEmployee>()
{
new ENTEmployee(){ Id = "b977ec04-3bd7-4691-b4eb-ef47ed6796fd", FullName = "AAA BBB", Salary = 15000 },
new ENTEmployee(){ Id = "c670a3e2-b13f-42b3-849c-fd792ebfd103", FullName = "BBB BBB", Salary = 16000 },
new ENTEmployee(){ Id = "d961c33c-0244-48dc-8e10-f4f012386eb6", FullName = "CCC BBB", Salary = 17000 },
new ENTEmployee(){ Id = "35be4508-ff93-4be8-983f-d4908bcc592d", FullName = "DDD BBB", Salary = 18000 },
new ENTEmployee(){ Id = "0875549c-d06c-4983-b89a-edf81b6aa70d", FullName = "EEE BBB", Salary = 19000 },
};
var insertResult = conn.InsertAll(employees);
//Updated Record
employees[0].FullName = "AAA Updated";
employees[0].Salary = 12300;
//New Records
employees.Add(new ENTEmployee() { Id = "87f48ecf-715c-4327-9ef3-11712ba4a120", FullName = "FFF BBB", Salary = 20000 });
employees.Add(new ENTEmployee() { Id = "85f53888-b1e9-460c-8d79-88010f143bcf", FullName = "GGG BBB", Salary = 21000 });
//Now here,
//How to decide which records to be inserted and which records to be updated for List employees?
}
How to Insert Or Replace all my records at once in this case?
有两种方法可以解决问题L:
遍历您的记录列表并对列表中的每个对象使用
conn.InsertOrReplace(object)
:for(ENTEmployee emp in employees) { conn.InsertOrReplace(雇员); }
使用Sql命令插入或替换记录(需要您构造命令字符串):
string cmd = @"insert or replace into employ(id,FullName,salary) values('c670a3e2-b13f-42b3-849c-fd792ebfd103', 'fullname1',32), ('d961c33c-0244-48dc-8e10-f4f012386eb6', 'fullname2',23);"; conn.Execute(cmd);
我实现了一个与他们的实现类似的扩展方法。您可以将其与 SQLite.Net-PCL
project.
static public class SQLiteConnectionExtensions
{
/// <summary>
/// Inserts all specified objects.
/// For each insertion, if a UNIQUE
/// constraint violation occurs with
/// some pre-existing object, this function
/// deletes the old object.
/// </summary>
/// <param name="objects">
/// An <see cref="IEnumerable" /> of the objects to insert or replace.
/// </param>
/// <returns>
/// The total number of rows modified.
/// </returns>
static public int InsertOrReplaceAll(this SQLiteConnection connection, IEnumerable objects, bool runInTransaction = true)
{
var c = 0;
if (objects == null)
return c;
if (runInTransaction)
{
connection.RunInTransaction(() =>
{
foreach (var r in objects)
{
c += connection.Insert(r, "OR REPLACE", Orm.GetType(r));
}
});
}
else
{
foreach (var r in objects)
{
c += connection.Insert(r, "OR REPLACE", Orm.GetType(r));
}
}
return c;
}
}
刚刚对 4 种不同的方式进行了基准测试来更新许多项目:
上下文:更新包含 5000 个项目的产品(每个对象有 7 个属性)数据库。
- 在 foreach 循环中使用 exists(通过 PK 上的 countasync)、insertasync 和 updateasync:大约 30 秒
- 使用 foreach 循环和 InsertOrReplaceAsync:大约 2 分钟
- 使用@Genfood 提出的扩展:大约 92 毫秒
- 使用@Elvis Xia 建议的手动查询 - MSFT:大约 81 毫秒
我刚刚对扩展进行了一些修改以管理异步方法的使用
public static class SqliteExtensions
{
static async public Task<int> InsertOrReplaceAll(this SQLiteAsyncConnection connection, IEnumerable objects, bool runInTransaction = true)
{
var c = 0;
if (objects == null)
return c;
if (runInTransaction)
{
await connection.RunInTransactionAsync(nonAsyncConnection =>
{
foreach (var r in objects)
{
c += nonAsyncConnection.Insert(r, "OR REPLACE", Orm.GetType(r));
}
});
}
else
{
foreach (var r in objects)
{
c += await connection.InsertAsync(r, "OR REPLACE", Orm.GetType(r));
}
}
return c;
}
}