public void Query_Parallel() { using (var db = new LiteDatabase(new MemoryStream())) { var col = db.GetCollection <Person>("person"); var all = DataGen.Person().ToArray(); col.Insert(all); var bag = new ConcurrentBag <Person>(); var people = col.FindAll(); Parallel.ForEach(people, person => //foreach(var person in people) { var col2 = db.GetCollection <Person>("person"); var exists = col2.Exists(x => x.Id == person.Id); if (exists) { var col3 = db.GetCollection <Person>("person"); var item = col3.FindOne(x => x.Id == person.Id); bag.Add(item); } }); all.Length.Should().Be(bag.Count); } }
public Person_Tests() { this.local = DataGen.Person().ToArray(); db = new LiteDatabase(":memory:"); collection = db.GetCollection <Person>("person"); collection.Insert(this.local); }
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())) { var person = db.GetCollection <Person>(); // init person collection with 100 document person.Insert(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(() => { db.BeginTrans(); person.Insert(data2); taskBSemaphore.Release(); taskASemaphore.Wait(); var count = person.Count(); count.Should().Be(data1.Length + data2.Length); db.Commit(); 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 GroupBy_Tests() { local = DataGen.Person(1, 1000).ToArray(); db = new LiteDatabase(new MemoryStream()); collection = db.GetCollection <Person>(); collection.Insert(local); collection.EnsureIndex(x => x.Age); }
public void Transaction_Avoid_Drity_Read() { var data1 = DataGen.Person(1, 100).ToArray(); var data2 = DataGen.Person(101, 200).ToArray(); using (var db = new LiteDatabase(new MemoryStream())) { var person = db.GetCollection <Person>(); // init person collection with 100 document person.Insert(data1); // 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 = new Task(() => { db.BeginTrans(); person.Insert(data2); Task.Delay(1000).Wait(); var count = person.Count(); Assert.AreEqual(data1.Length + data2.Length, count); db.Commit(); }); // 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 cann't see (are not commited yet) // after task A finish, I can see now all 200 documents var tb = new Task(() => { Task.Delay(250).Wait(); var count = person.Count(); // read 100 documents Assert.AreEqual(data1.Length, count); ta.Wait(); // read 200 documets count = person.Count(); Assert.AreEqual(data1.Length + data2.Length, count); }); ta.Start(); tb.Start(); Task.WaitAll(ta, tb); } }
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())) { var person = db.GetCollection <Person>(); // init person collection with 100 document person.Insert(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(() => { db.BeginTrans(); person.Insert(data2); taskBSemaphore.Release(); taskASemaphore.Wait(); db.Commit(); 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:")) { // small timeout db.Pragma(Pragmas.TIMEOUT, 1); var person = db.GetCollection <Person>(); // init person collection with 100 document person.Insert(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(() => { db.BeginTrans(); person.Insert(data2); taskBSemaphore.Release(); taskASemaphore.Wait(); var count = person.Count(); count.Should().Be(data1.Length + data2.Length); db.Commit(); }); // 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 void 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:;timeout=1")) { var person = db.GetCollection <Person>(); // init person collection with 100 document person.Insert(data1); // task A will open transaction and will insert +100 documents // but will commit only 2s later var ta = new Task(() => { db.BeginTrans(); person.Insert(data2); Task.Delay(4000).Wait(); var count = person.Count(); Assert.AreEqual(data1.Length + data2.Length, count); db.Commit(); }); // task B will try delete all documents but will be locked during 1 second var tb = new Task(() => { Task.Delay(250).Wait(); db.BeginTrans(); try { person.DeleteMany("1 = 1"); Assert.Fail("Must be locked"); } catch (LiteException ex) when(ex.ErrorCode == LiteException.LOCK_TIMEOUT) { } }); ta.Start(); tb.Start(); Task.WaitAll(ta, tb); } }
public void Transaction_Read_Version() { var data1 = DataGen.Person(1, 100).ToArray(); var data2 = DataGen.Person(101, 200).ToArray(); using (var db = new LiteDatabase(new MemoryStream())) { var person = db.GetCollection <Person>(); // init person collection with 100 document person.Insert(data1); // task A will insert more 100 documents but will commit only 1s later var ta = new Task(() => { db.BeginTrans(); person.Insert(data2); Task.Delay(1000).Wait(); db.Commit(); }); // 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 = new Task(() => { db.BeginTrans(); Task.Delay(250).Wait(); var count = person.Count(); // read 100 documents Assert.AreEqual(data1.Length, count); ta.Wait(); // keep reading 100 documets because i'm still in same transaction count = person.Count(); Assert.AreEqual(data1.Length, count); }); ta.Start(); tb.Start(); Task.WaitAll(ta, tb); } }
public void Test_Transaction_States() { var data0 = DataGen.Person(1, 10).ToArray(); var data1 = DataGen.Person(11, 20).ToArray(); using (var db = new LiteDatabase(new MemoryStream())) { var person = db.GetCollection <Person>(); // first time transaction will be opened Assert.IsTrue(db.BeginTrans()); // but in second type transaction will be same Assert.IsFalse(db.BeginTrans()); person.Insert(data0); // must commit transaction Assert.IsTrue(db.Commit()); // no transaction to commit Assert.IsFalse(db.Commit()); // no transaction to rollback; Assert.IsFalse(db.Rollback()); Assert.IsTrue(db.BeginTrans()); // no page was changed but ok, let's rollback anyway Assert.IsTrue(db.Rollback()); // auto-commit person.Insert(data1); Assert.AreEqual(20, person.Count()); } }
public Person_Tests() { this.local = DataGen.Person().ToArray(); }