diff --git a/src/SQLite.cs b/src/SQLite.cs index 1697fe9f..deed56ce 100644 --- a/src/SQLite.cs +++ b/src/SQLite.cs @@ -242,6 +242,8 @@ CreateTablesResult CreateTables (CreateFlags createFlags = Cr int InsertAll (IEnumerable objects, Type objType, bool runInTransaction = true); int InsertOrReplace (object obj); int InsertOrReplace (object obj, Type objType); + int InsertOrReplaceAll(IEnumerable objects, bool runInTransaction = true); + int InsertOrReplaceAll(IEnumerable objects, Type objType, bool runInTransaction = true); List Query (string query, params object[] args) where T : new(); List Query (TableMapping map, string query, params object[] args); List QueryScalars (string query, params object[] args); @@ -1731,6 +1733,57 @@ public int InsertAll (System.Collections.IEnumerable objects, Type objType, bool return c; } + /// + /// Inserts all specified objects. + /// + /// + /// An of the objects to insert. + /// + /// A boolean indicating if the inserts should be wrapped in a transaction. + /// + /// + /// + /// The number of rows added to the table. + /// + public int InsertOrReplaceAll(IEnumerable objects, bool runInTransaction = true) + { + var c = 0; + if (runInTransaction) { + RunInTransaction(() => { c += objects.Cast().Sum(InsertOrReplace); }); + } + else { + c += objects.Cast().Sum(InsertOrReplace); + } + return c; + } + + /// + /// Inserts all specified objects. + /// + /// + /// An of the objects to insert. + /// + /// + /// The type of object to insert. + /// + /// + /// A boolean indicating if the inserts should be wrapped in a transaction. + /// + /// + /// The number of rows added to the table. + /// + public int InsertOrReplaceAll(IEnumerable objects, Type objType, bool runInTransaction = true) + { + var c = 0; + if (runInTransaction) { + RunInTransaction(() => { c += objects.Cast().Sum(r => InsertOrReplace(r, objType)); }); + } + else { + c += objects.Cast().Sum(r => InsertOrReplace(r, objType)); + } + return c; + } + /// /// Inserts the given object (and updates its /// auto incremented primary key if it has one). diff --git a/tests/SQLite.Tests/InsertTest.cs b/tests/SQLite.Tests/InsertTest.cs index 57dcd7a2..bad74a1b 100644 --- a/tests/SQLite.Tests/InsertTest.cs +++ b/tests/SQLite.Tests/InsertTest.cs @@ -279,5 +279,51 @@ public void InsertOrReplace () Assert.AreEqual (20, r.Count); Assert.AreEqual ("Foo", r[4].Text); } + + [Test] + public void InsertOrReplaceAllSuccessOutsideTransaction() + { + var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); + + _db.InsertOrReplaceAll(testObjects); + + Assert.AreEqual(testObjects.Count, _db.Table().Count()); + } + + [Test] + public void InsertOrReplaceAllFailureOutsideTransaction() + { + var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); + testObjects[^1].Id = 1; // causes the insert to fail because of duplicate key + + ExceptionAssert.Throws(() => _db.InsertAll(testObjects)); + + Assert.AreEqual(0, _db.Table().Count()); + } + + [Test] + public void InsertOrReplaceAllSuccessInsideTransaction() + { + var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); + + _db.RunInTransaction(() => { + _db.InsertOrReplaceAll(testObjects); + }); + + Assert.AreEqual(testObjects.Count, _db.Table().Count()); + } + + [Test] + public void InsertOrReplaceAllFailureInsideTransaction() + { + var testObjects = Enumerable.Range(1, 20).Select(i => new UniqueObj { Id = i }).ToList(); + testObjects[^1].Id = 1; // causes the insert to fail because of duplicate key + + ExceptionAssert.Throws(() => _db.RunInTransaction(() => { + _db.InsertOrReplaceAll(testObjects); + })); + + Assert.AreEqual(0, _db.Table().Count()); + } } }