3

我想删除SQLite.Net-PCL包并想使用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?
}
4

3 回答 3

2

我实现了一个与他们的实现类似的扩展方法。您可以将其与SQLite.Net-PCL 项目中的原始版本进行比较。

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;
    }
}
于 2018-07-04T13:23:16.383 回答
1

在这种情况下如何一次插入或替换我的所有记录?

有两种方法可以解决问题L:

  1. 遍历您的记录列表并conn.InsertOrReplace(object)用于列表中的每个对象:

    for(ENTEmployee emp in employees) { conn.InsertOrReplace(emp); }

  2. 使用 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);
    
于 2017-11-06T07:21:48.707 回答
0

刚刚基准测试了 4 种不同的方法来更新许多项目:

上下文:更新包含 5000 个项目的产品(每个对象中有 7 个属性)数据库。

  1. 在 foreach 循环中使用存在(通过 PK 上的 countasync)、insertasync 和 updateasync:大约 30 秒
  2. 使用 foreach 循环和 InsertOrReplaceAsync :大约 2 分钟
  3. 使用@Genfood 提出的扩展:大约 92 毫秒
  4. 使用@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;
    }
}
于 2020-01-15T13:18:55.873 回答