public async Task Insert_With_AutoId_And_Reread() { using (var db = new LiteDatabaseAsync(new MemoryStream())) { var users = db.GetCollection <User>("TEST"); var u1 = new User { Name = "John" }; var u2 = new User { Name = "Zarlos" }; var u3 = new User { Name = "Ana" }; // insert ienumerable await users.InsertAsync(new User[] { u1, u2, u3 }); // Reopen the collection var users2 = db.GetCollection <User>("TEST"); var result = users2.FindAllAsync().GetAwaiter().GetResult(); Assert.Equal(3, result.Count()); var resultList = result.Select(u => u.Name).ToList(); Assert.Contains("John", resultList); Assert.Contains("Zarlos", resultList); Assert.Contains("Ana", resultList); } }
public async Task UpsertManyAsync() { using (var db = new LiteDatabaseAsync(new MemoryStream())) { var manyUsers = Enumerable.Range(1, 100).Select(i => new User() { Id = i, Name = $"Example {i}" }).ToList(); var users = db.GetCollection <User>("users"); Assert.Equal(100, await users.UpsertAsync(manyUsers)); Assert.Equal(100, await users.CountAsync()); // Read back from the database var users2 = await db.GetCollection <User>("users").Query().ToListAsync(); // Are the id values the expected ones Assert.True(Enumerable.Range(1, 100).ToHashSet().SetEquals(users2.Select(u => u.Id))); // Are the names correct? foreach (var user in users2) { Assert.Equal($"Example {user.Id}", user.Name); } // Update with new names manyUsers = Enumerable.Range(1, 100).Select(i => new User() { Id = i, Name = $"User {i}" }).ToList(); await users.UpsertAsync(manyUsers); Assert.Equal(100, await users.CountAsync()); // Read back from the database users2 = await db.GetCollection <User>("users").Query().ToListAsync(); // Are the id values the expected ones Assert.True(Enumerable.Range(1, 100).ToHashSet().SetEquals(users2.Select(u => u.Id))); // Are the names correct? foreach (var user in users2) { Assert.Equal($"User {user.Id}", user.Name); } } }
public async Task Transaction_Avoid_Dirty_Read() { var data1 = DataGen.Person(1, 100).ToArray(); var data2 = DataGen.Person(101, 200).ToArray(); using (var db = new LiteDatabase(new MemoryStream())) using (var asyncDb = new LiteDatabaseAsync(db, false)) { var asyncPerson = asyncDb.GetCollection <Person>(); var person = db.GetCollection <Person>(); // init person collection with 100 document await asyncPerson.InsertAsync(data1); var taskASemaphore = new SemaphoreSlim(0, 1); var taskBSemaphore = new SemaphoreSlim(0, 1); // task A will open transaction and will insert +100 documents // but will commit only 1s later - this plus +100 document must be visible only inside task A var ta = Task.Run(async() => { await asyncDb.BeginTransAsync(); await asyncPerson.InsertAsync(data2); taskBSemaphore.Release(); await taskASemaphore.WaitAsync(); var count = await asyncPerson.CountAsync(); count.Should().Be(data1.Length + data2.Length); await asyncDb.CommitAsync(); taskBSemaphore.Release(); }); // task B will not open transaction and will wait 250ms before and count collection - // at this time, task A already insert +100 document but here I can't see (are not committed yet) // after task A finish, I can see now all 200 documents var tb = Task.Run(() => { taskBSemaphore.Wait(); var count = person.Count(); // read 100 documents count.Should().Be(data1.Length); taskASemaphore.Release(); taskBSemaphore.Wait(); // read 200 documents count = person.Count(); count.Should().Be(data1.Length + data2.Length); }); await Task.WhenAll(ta, tb); } }
public async Task Delete_Many() { using (var db = new LiteDatabaseAsync(new MemoryStream())) { var users = db.GetCollection <User>("users"); var u1 = new User { Id = 1, Name = "John" }; var u2 = new User { Id = 2, Name = "Zarlos" }; var u3 = new User { Id = 3, Name = "Ana" }; await users.InsertAsync(new User[] { u1, u2, u3 }); var ids = new int[] { 1, 2, 3 }; await users.DeleteManyAsync(x => ids.Contains(x.Id)); (await users.CountAsync()).Should().Be(0); } }
public IndexSortAndFilterTest() { _tempFile = new TempFile(); _database = new LiteDatabaseAsync(_tempFile.Filename); _collection = _database.GetCollection <Item>("items"); var task1 = _collection.UpsertAsync(new Item() { Id = "C", Value = "Value 1" }); var task2 = _collection.UpsertAsync(new Item() { Id = "A", Value = "Value 2" }); var task3 = _collection.UpsertAsync(new Item() { Id = "B", Value = "Value 1" }); Task.WaitAll(task1, task2, task3); var task4 = _collection.EnsureIndexAsync("idx_value", x => x.Value); task4.Wait(); }
public async Task Query_Min_Max() { using (var f = new TempFile()) using (var db = new LiteDatabaseAsync(f.Filename)) { var c = db.GetCollection <EntityMinMax>("col"); await c.InsertAsync(new EntityMinMax { }); await c.InsertAsync(new EntityMinMax { ByteValue = 200, IntValue = 443500, LongValue = 443500, UintValue = 443500 }); await c.EnsureIndexAsync(x => x.ByteValue); await c.EnsureIndexAsync(x => x.IntValue); await c.EnsureIndexAsync(x => x.LongValue); await c.EnsureIndexAsync(x => x.UintValue); (await c.MaxAsync(x => x.ByteValue)).Should().Be(200); (await c.MaxAsync(x => x.IntValue)).Should().Be(443500); (await c.MaxAsync(x => x.LongValue)).Should().Be(443500); (await c.MaxAsync(x => x.UintValue)).Should().Be(443500); } }
public async Task Rebuild_Change_Culture_Error() { using (var file = new TempFile()) using (var db = new LiteDatabaseAsync(file.Filename)) { // remove string comparer ignore case await db.RebuildAsync(new RebuildOptions { Collation = new Collation("en-US/None") }); // insert 2 documents with different ID in case sensitive await db.GetCollection("col1").InsertAsync(new BsonDocument[] { new BsonDocument { ["_id"] = "ana" }, new BsonDocument { ["_id"] = "ANA" } }); // try migrate to ignorecase this.Invoking(async x => { await db.RebuildAsync(new RebuildOptions { Collation = new Collation("en-US/IgnoreCase") }); }).Should().Throw <LiteAsyncException>(); // test if current pragma still with collation none (await db.PragmaAsync(Pragmas.COLLATION)).AsString.Should().Be("en-US/None"); } }
public async Task FindAll() { using (var f = new TempFile()) { using (var db = new LiteDatabaseAsync(f.Filename)) { var col = db.GetCollection <Person>("Person"); await col.InsertAsync(new Person { Fullname = "John" }); await col.InsertAsync(new Person { Fullname = "Doe" }); await col.InsertAsync(new Person { Fullname = "Joana" }); await col.InsertAsync(new Person { Fullname = "Marcus" }); } // close datafile using (var db = new LiteDatabaseAsync(f.Filename)) { var p = await db.GetCollection <Person>("Person").FindAsync(Query.All("Fullname", Query.Ascending)); p.Count().Should().Be(4); } } }
public async Task NamedIndexWasCorrectlyCreated() { // Too fix https://github.com/mlockett42/litedb-async/issues/12 var indexes = _database.GetCollection("$indexes"); var indexContent = await indexes.Query().ToListAsync(); Assert.Single(indexContent.Where(x => x["name"] == "idx_value")); }
public async Task Transaction_Read_Version() { var data1 = DataGen.Person(1, 100).ToArray(); var data2 = DataGen.Person(101, 200).ToArray(); using (var db = new LiteDatabase(new MemoryStream())) using (var asyncDb = new LiteDatabaseAsync(db, false)) { var asyncPerson = asyncDb.GetCollection <Person>(); var person = db.GetCollection <Person>(); // init person collection with 100 document await asyncPerson.InsertAsync(data1); var taskASemaphore = new SemaphoreSlim(0, 1); var taskBSemaphore = new SemaphoreSlim(0, 1); // task A will insert more 100 documents but will commit only 1s later var ta = Task.Run(async() => { await asyncDb.BeginTransAsync(); await asyncPerson.InsertAsync(data2); taskBSemaphore.Release(); taskASemaphore.Wait(); await asyncDb.CommitAsync(); taskBSemaphore.Release(); }); // task B will open transaction too and will count 100 original documents only // but now, will wait task A finish - but is in transaction and must see only initial version var tb = Task.Run(() => { db.BeginTrans(); taskBSemaphore.Wait(); var count = person.Count(); // read 100 documents count.Should().Be(data1.Length); taskASemaphore.Release(); taskBSemaphore.Wait(); // keep reading 100 documents because i'm still in same transaction count = person.Count(); count.Should().Be(data1.Length); }); await Task.WhenAll(ta, tb); } }
public async Task Transaction_Write_Lock_Timeout() { var data1 = DataGen.Person(1, 100).ToArray(); var data2 = DataGen.Person(101, 200).ToArray(); using (var db = new LiteDatabase("filename=:memory:")) using (var asyncDb = new LiteDatabaseAsync(db, false)) { // small timeout await asyncDb.PragmaAsync(Pragmas.TIMEOUT, 1); var asyncPerson = asyncDb.GetCollection <Person>(); var person = db.GetCollection <Person>(); // init person collection with 100 document await asyncPerson.InsertAsync(data1); var taskASemaphore = new SemaphoreSlim(0, 1); var taskBSemaphore = new SemaphoreSlim(0, 1); // task A will open transaction and will insert +100 documents // but will commit only 2s later var ta = Task.Run(async() => { await asyncDb.BeginTransAsync(); await asyncPerson.InsertAsync(data2); taskBSemaphore.Release(); taskASemaphore.Wait(); var count = await asyncPerson.CountAsync(); count.Should().Be(data1.Length + data2.Length); await asyncDb.CommitAsync(); }); // task B will try delete all documents but will be locked during 1 second var tb = Task.Run(() => { taskBSemaphore.Wait(); db.BeginTrans(); person .Invoking(personCol => personCol.DeleteMany("1 = 1")) .Should() .Throw <LiteException>() .Where(ex => ex.ErrorCode == LiteException.LOCK_TIMEOUT); taskASemaphore.Release(); }); await Task.WhenAll(ta, tb); } }
public async Task Rebuild_Large_Files() { // do some tests async Task DoTestAsync(ILiteDatabaseAsync db, ILiteCollectionAsync <Zip> col) { Assert.Equal(1, await col.CountAsync()); Assert.Equal(99, db.UserVersion); }; using (var file = new TempFile()) { using (var db = new LiteDatabaseAsync(file.Filename)) { var col = db.GetCollection <Zip>(); db.UserVersion = 99; await col.EnsureIndexAsync("city", false); var inserted = await col.InsertAsync(DataGen.Zip()); // 29.353 docs var deleted = await col.DeleteManyAsync(x => x.Id != "01001"); // delete 29.352 docs Assert.Equal(29353, inserted); Assert.Equal(29352, deleted); Assert.Equal(1, await col.CountAsync()); // must checkpoint await db.CheckpointAsync(); // file still large than 5mb (even with only 1 document) Assert.True(file.Size > 5 * 1024 * 1024); // reduce datafile var reduced = await db.RebuildAsync(); // now file are small than 50kb Assert.True(file.Size < 50 * 1024); await DoTestAsync(db, col); } // re-open and rebuild again using (var db = new LiteDatabaseAsync(file.Filename)) { var col = db.GetCollection <Zip>(); await DoTestAsync(db, col); await db.RebuildAsync(); await DoTestAsync(db, col); } } }
public Person_Tests() { this.local = DataGen.Person().ToArray(); _db = new LiteDatabaseAsync(":memory:"); _collection = _db.GetCollection <Person>("person"); var task = _collection.InsertAsync(this.local); task.Wait(); }
public async Task MultiKey_Mapper() { using (var db = new LiteDatabaseAsync(":memory:")) { var col = db.GetCollection <MultiKeyDoc>("col"); await col.InsertAsync(new MultiKeyDoc { Id = 1, Keys = new int[] { 1, 2, 3 }, Customers = new List <Customer>() { new Customer { Name = "John" }, new Customer { Name = "Ana" }, new Customer { Name = "Doe" }, new Customer { Name = "Dante" } } }); await col.InsertAsync(new MultiKeyDoc { Id = 2, Keys = new int[] { 2 }, Customers = new List <Customer>() { new Customer { Name = "Ana" } } }); await col.EnsureIndexAsync(x => x.Keys); await col.EnsureIndexAsync(x => x.Customers.Select(z => z.Name)); // Query.EQ("Keys", 2) (await col.CountAsync(Query.Any().EQ("Keys", 2))).Should().Be(2); (await col.CountAsync(x => x.Keys.Contains(2))).Should().Be(2); (await col.CountAsync(Query.StartsWith("Customers[*].Name ANY", "Ana"))).Should().Be(2); (await col.CountAsync(x => x.Customers.Select(z => z.Name).Any(z => z.StartsWith("Ana")))).Should().Be(2); (await col.CountAsync(Query.StartsWith("Customers[*].Name ANY", "D"))).Should().Be(1); (await col.CountAsync(x => x.Customers.Select(z => z.Name).Any(z => z.StartsWith("D")))).Should().Be(1); } }
private async Task <LiteCollectionAsync <PlayHistory> > _getPlayHistoryCollection() { var collection = _db.GetCollection <PlayHistory>("play_history"); await collection.EnsureIndexAsync(x => x.Id); await collection.EnsureIndexAsync(x => x.VoiceChannelId); await collection.EnsureIndexAsync(x => x.MetadataId); return(collection); }
public async Task AutoId_Zero_Int() { using (var db = new LiteDatabaseAsync(":memory:")) { var test = db.GetCollection("Test", BsonAutoId.Int32); var doc = new BsonDocument() { ["_id"] = 0, ["p1"] = 1 }; await test.InsertAsync(doc); // -> NullReferenceException } }
public async Task DbRef_Index() { var mapper = new BsonMapper(); mapper.Entity <Customer>() .Id(x => x.Login) .Field(x => x.Name, "customer_name"); mapper.Entity <Order>() .Id(x => x.OrderNumber) .Field(x => x.Customer, "cust") .DbRef(x => x.Customer, "customers"); using (var db = new LiteDatabaseAsync(new MemoryStream(), mapper)) { var customer = new Customer { Login = "******", Name = "John Doe" }; var order = new Order { Customer = customer }; var customers = db.GetCollection <Customer>("Customers"); var orders = db.GetCollection <Order>("Orders"); await customers.InsertAsync(customer); await orders.InsertAsync(order); // create an index in Customer.Id ref // x.Customer.Login == "Customer.$id" await orders.EnsureIndexAsync(x => x.Customer.Login); var query = await orders .Include(x => x.Customer) .FindOneAsync(x => x.Customer.Login == "jd"); query.Customer.Name.Should().Be(customer.Name); } }
private async Task <LiteCollectionAsync <Metadata> > _getMetadataCollection() { var collection = _db.GetCollection <Metadata>("metadata"); await collection.EnsureIndexAsync(x => x.Id); await collection.EnsureIndexAsync(x => x.RedditId); await collection.EnsureIndexAsync(x => x.Type); await collection.EnsureIndexAsync(x => x.Url); return(collection); }
public async Task TestCanUpsertAndGetList() { var collection = _db.GetCollection <SimplePerson>(); var person = new SimplePerson() { Id = Guid.NewGuid(), FirstName = "John", LastName = "Smith" }; var upsertResult = await collection.UpsertAsync(person); Assert.True(upsertResult); var listResult = await collection.Query().ToListAsync(); Assert.Single(listResult); var resultPerson = listResult[0]; Assert.Equal(person.Id, resultPerson.Id); Assert.Equal(person.FirstName, resultPerson.FirstName); Assert.Equal(person.LastName, resultPerson.LastName); }
public async Task TestOpeningDatabaseASecondTimeCausesAnException() { string databasePath = Path.Combine(Path.GetTempPath(), "litedbn-async-testing-" + Path.GetRandomFileName() + ".db"); using (var db1 = new LiteDatabaseAsync(databasePath)) { await db1.GetCollection <SimplePerson>().InsertAsync(new SimplePerson()); await Assert.ThrowsAsync <IOException>(async() => { using var db2 = new LiteDatabaseAsync(databasePath); await db2.GetCollection <SimplePerson>().InsertAsync(new SimplePerson()); }); } File.Delete(databasePath); }
public async Task TestCanDisposeDatabaseTimely() { string databasePath = Path.Combine(Path.GetTempPath(), "litedbn-async-testing-" + Path.GetRandomFileName() + ".db"); var db = new LiteDatabaseAsync(databasePath); // Ensure to do some stuff to open the database var collection = db.GetCollection <SimplePerson>(); await collection.InsertAsync(new SimplePerson()).ConfigureAwait(false); var stopwatch = Stopwatch.StartNew(); db.Dispose(); stopwatch.Stop(); Assert.InRange(stopwatch.Elapsed.TotalSeconds, 0, 4.99); }
public async Task DropCollection() { using (var file = new TempFile()) using (var db = new LiteDatabaseAsync(file.Filename)) { (await db.GetCollectionNamesAsync()).Should().NotContain("col"); var col = db.GetCollection("col"); await col.InsertAsync(new BsonDocument { ["a"] = 1 }); (await db.GetCollectionNamesAsync()).Should().Contain("col"); await db.DropCollectionAsync("col"); (await db.GetCollectionNamesAsync()).Should().NotContain("col"); } }
public async Task Insert_With_AutoId() { using (var wrappedDb = new LiteDatabase(new MemoryStream())) using (var db = new LiteDatabaseAsync(wrappedDb)) { var users = db.GetCollection <User>("users"); var u1 = new User { Name = "John" }; var u2 = new User { Name = "Zarlos" }; var u3 = new User { Name = "Ana" }; // insert ienumerable await users.InsertAsync(new User[] { u1, u2 }); await users.InsertAsync(u3); // test auto-id u1.Id.Should().Be(1); u2.Id.Should().Be(2); u3.Id.Should().Be(3); // adding without autoId var u4 = new User { Id = 20, Name = "Marco" }; await users.InsertAsync(u4); // adding more auto id after fixed id var u5 = new User { Name = "Julio" }; await users.InsertAsync(u5); u5.Id.Should().Be(21); } }
public async Task TestCanRoundtripUtcDateTime() { var collection = _db.GetCollection <ThingThatHappened>(); var now = new DateTime(1979, 3, 19, 12, 00, 00, DateTimeKind.Utc); var evt = new ThingThatHappened { Time = now }; var upsertResult = await collection.UpsertAsync(evt); Assert.True(upsertResult); var listResult = await collection.Query().ToListAsync(); Assert.Single(listResult); var resultThing = listResult[0]; Assert.Equal(now, resultThing.Time); }
public async Task InsertDropCollection() { using (var file = new TempFile()) { using (var db = new LiteDatabaseAsync(file.Filename)) { var col = db.GetCollection("test"); await col.InsertAsync(new BsonDocument { ["_id"] = 1 }); await db.DropCollectionAsync("test"); await db.RebuildAsync(); } using (var db = new LiteDatabaseAsync(file.Filename)) { var col = db.GetCollection("test"); await col.InsertAsync(new BsonDocument { ["_id"] = 1 }); } } }
public async Task AutoId_BsonDocument() { using (var db = new LiteDatabaseAsync(new MemoryStream())) { var col = db.GetCollection("Writers"); await col.InsertAsync(new BsonDocument { ["Name"] = "Mark Twain" }); await col.InsertAsync(new BsonDocument { ["Name"] = "Jack London", ["_id"] = 1 }); // create an index in name field await col.EnsureIndexAsync("LowerName", "LOWER($.Name)"); var mark = await col.FindOneAsync(Query.EQ("LOWER($.Name)", "mark twain")); var jack = await col.FindOneAsync(Query.EQ("LOWER($.Name)", "jack london")); // checks if auto-id is a ObjectId mark["_id"].IsObjectId.Should().BeTrue(); jack["_id"].IsInt32.Should().BeTrue(); // jack do not use AutoId (fixed in int32) } }
public async Task Delete_By_Name() { using (var f = new TempFile()) using (var db = new LiteDatabaseAsync(f.Filename)) { var col = db.GetCollection <Person>("Person"); await col.InsertAsync(new Person { Fullname = "John" }); await col.InsertAsync(new Person { Fullname = "Doe" }); await col.InsertAsync(new Person { Fullname = "Joana" }); await col.InsertAsync(new Person { Fullname = "Marcus" }); // lets auto-create index in FullName and delete from a non-pk node var del = await col.DeleteManyAsync(x => x.Fullname.StartsWith("J")); del.Should().Be(2); } }
public async Task Rebuild_After_DropCollection() { using (var file = new TempFile()) using (var db = new LiteDatabaseAsync(file.Filename)) { var col = db.GetCollection <Zip>("zip"); await col.InsertAsync(DataGen.Zip()); await db.DropCollectionAsync("zip"); await db.CheckpointAsync(); // full disk usage var size = file.Size; var r = await db.RebuildAsync(); // only header page Assert.Equal(8192, size - r); } }
public async Task Transaction_Update_Upsert() { using var db = new LiteDatabaseAsync(":memory:"); var col = db.GetCollection("test"); // Transactions not supported ATM by Async //bool transactionCreated = db.BeginTrans(); //Assert.True(transactionCreated); int updatedDocs = await col.UpdateManyAsync("{name: \"xxx\"}", BsonExpression.Create("_id = 1")); Assert.Equal(0, updatedDocs); await col.UpsertAsync(new BsonDocument() { ["_id"] = 1, ["name"] = "xxx" }); var result = await col.FindByIdAsync(1); Assert.NotNull(result); }
public async Task MissingIdDoc_Test() { using (var file = new TempFile()) using (var db = new LiteDatabaseAsync(file.Filename)) { var col = db.GetCollection <MissingIdDoc>("col"); var p = new MissingIdDoc { Name = "John", Age = 39 }; // ObjectID will be generated var id = await col.InsertAsync(p); p.Age = 41; await col.UpdateAsync(id, p); var r = await col.FindByIdAsync(id); r.Name.Should().Be(p.Name); } }