From 08516f92cfbe1dd275669d21af263703ba34a648 Mon Sep 17 00:00:00 2001 From: Sam Corder Date: Sat, 20 Mar 2010 22:34:18 -0400 Subject: [PATCH] Making the current branch more backward compatible. --- MongoDB.Driver.Benchmark/Main.cs | 2 +- MongoDB.GridFS/GridFile.cs | 12 +- MongoDB.GridFS/GridFileStream.cs | 10 +- .../TestMongoDocumentQuerySyntax.cs | 10 +- MongoDB.Linq.Tests/TestQueryParsing.cs | 8 +- MongoDB.Linq/MongoLinqEx.cs | 4 +- MongoDB.Linq/MongoQueryProvider.cs | 6 +- MongoDB.Net-Tests/TestCollection.cs | 48 +- MongoDB.Net-Tests/TestCollectionMetaData.cs | 2 +- MongoDB.Net-Tests/TestCollectionSafeMode.cs | 10 +- MongoDB.Net-Tests/TestConcurrency.cs | 12 +- MongoDB.Net-Tests/TestCursor.cs | 16 +- MongoDB.Net-Tests/TestDatabase.cs | 8 +- MongoDB.Net-Tests/TestDatabaseJavascript.cs | 2 +- MongoDB.Net-Tests/TestMapReduce.cs | 2 +- MongoDB.Net-Tests/TestMapReduceBuilder.cs | 2 +- MongoDBDriver/Cursor.cs | 117 +-- MongoDBDriver/DatabaseJavascript.cs | 2 +- MongoDBDriver/DatabaseMetaData.cs | 20 +- MongoDBDriver/Generic/Cursor.cs | 388 ++++++++++ MongoDBDriver/Generic/ICursor.cs | 25 + MongoDBDriver/Generic/IMongoCollection.cs | 396 ++++++++++ MongoDBDriver/Generic/MongoCollection.cs | 701 ++++++++++++++++++ MongoDBDriver/ICursor.cs | 29 +- MongoDBDriver/IMongoCollection.cs | 284 ++----- MongoDBDriver/IMongoDatabase.cs | 6 +- MongoDBDriver/MapReduce.cs | 4 +- MongoDBDriver/MongoCollection.cs | 81 +- MongoDBDriver/MongoDB.Driver.csproj | 12 +- MongoDBDriver/MongoDatabase.cs | 8 +- examples/Simple/Main.cs | 4 +- examples/SimpleVB/Application.vb | 4 +- 32 files changed, 1761 insertions(+), 474 deletions(-) create mode 100644 MongoDBDriver/Generic/Cursor.cs create mode 100644 MongoDBDriver/Generic/ICursor.cs create mode 100644 MongoDBDriver/Generic/IMongoCollection.cs create mode 100644 MongoDBDriver/Generic/MongoCollection.cs diff --git a/MongoDB.Driver.Benchmark/Main.cs b/MongoDB.Driver.Benchmark/Main.cs index da2cf090..8875f615 100644 --- a/MongoDB.Driver.Benchmark/Main.cs +++ b/MongoDB.Driver.Benchmark/Main.cs @@ -254,7 +254,7 @@ public static void Main (string[] args) static void DoFind(MongoDatabase db, string col, Document spec){ for(int i = 0; i < perTrial; i++){ - ICursor cur = db[col].Find(spec); + ICursor cur = db[col].Find(spec); foreach(Document d in cur.Documents){ } } diff --git a/MongoDB.GridFS/GridFile.cs b/MongoDB.GridFS/GridFile.cs index 2843fd3e..3a47f61c 100755 --- a/MongoDB.GridFS/GridFile.cs +++ b/MongoDB.GridFS/GridFile.cs @@ -13,14 +13,14 @@ public class GridFile{ get { return name; } } - private IMongoCollection files; - public IMongoCollection Files + private IMongoCollection files; + public IMongoCollection Files { get { return this.files; } } - private IMongoCollection chunks; - public IMongoCollection Chunks + private IMongoCollection chunks; + public IMongoCollection Chunks { get { return this.chunks; } } @@ -35,11 +35,11 @@ public IMongoCollection Chunks this.name = bucket; } - public ICursor ListFiles(){ + public ICursor ListFiles(){ return this.ListFiles(new Document()); } - public ICursor ListFiles(Document query) + public ICursor ListFiles(Document query) { return this.files.Find(new Document().Add("query", query) .Add("orderby", new Document() diff --git a/MongoDB.GridFS/GridFileStream.cs b/MongoDB.GridFS/GridFileStream.cs index 682152c4..f22666ba 100644 --- a/MongoDB.GridFS/GridFileStream.cs +++ b/MongoDB.GridFS/GridFileStream.cs @@ -19,8 +19,8 @@ namespace MongoDB.GridFS public class GridFileStream : Stream { - private IMongoCollection files; - private IMongoCollection chunks; + private IMongoCollection files; + private IMongoCollection chunks; private Document chunk; private bool chunkDirty; private long chunkLower = -1; @@ -65,8 +65,8 @@ public class GridFileStream : Stream } #endregion - public GridFileStream (GridFileInfo gridfileinfo, IMongoCollection files, - IMongoCollection chunks, FileAccess access) + public GridFileStream (GridFileInfo gridfileinfo, IMongoCollection files, + IMongoCollection chunks, FileAccess access) { switch (access) { case FileAccess.Read: @@ -364,7 +364,7 @@ private void EnsureNoHoles () Binary data = new Binary (this.blankBuffer); int i = 0; - using(ICursor cur = chunks.Find(new Document().Add("query", query).Add("sort", sort), 0, 0, fields)){ + using(ICursor cur = chunks.Find(new Document().Add("query", query).Add("sort", sort), 0, 0, fields)){ foreach (Document doc in cur.Documents) { int n = Convert.ToInt32 (doc["n"]); if (i < n) { diff --git a/MongoDB.Linq.Tests/TestMongoDocumentQuerySyntax.cs b/MongoDB.Linq.Tests/TestMongoDocumentQuerySyntax.cs index 2faad867..6f22396a 100644 --- a/MongoDB.Linq.Tests/TestMongoDocumentQuerySyntax.cs +++ b/MongoDB.Linq.Tests/TestMongoDocumentQuerySyntax.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Linq; using MongoDB.Driver; @@ -11,14 +11,14 @@ namespace MongoDB.Linq.Tests { public class TestMongoDocumentQuerySyntax { private IMongoQuery queryable; - private Mock> collectionMock; - private Mock> cursorMock; + private Mock collectionMock; + private Mock cursorMock; [SetUp] public void Setup() { Debug.WriteLine("initializing queryable"); - collectionMock = new Mock>(); - cursorMock = new Mock>(); + collectionMock = new Mock(); + cursorMock = new Mock(); collectionMock.Setup(c => c.Find(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cursorMock.Object); queryable = new MongoQuery(new MongoQueryProvider(collectionMock.Object)); } diff --git a/MongoDB.Linq.Tests/TestQueryParsing.cs b/MongoDB.Linq.Tests/TestQueryParsing.cs index 37bbabc8..f58cd03c 100644 --- a/MongoDB.Linq.Tests/TestQueryParsing.cs +++ b/MongoDB.Linq.Tests/TestQueryParsing.cs @@ -11,14 +11,14 @@ namespace MongoDB.Linq.Tests { public class TestQueryParsing { private IMongoQuery queryable; - private Mock> collectionMock; - private Mock> cursorMock; + private Mock collectionMock; + private Mock cursorMock; [SetUp] public void Setup() { Debug.WriteLine("initializing queryable"); - collectionMock = new Mock>(); - cursorMock = new Mock>(); + collectionMock = new Mock(); + cursorMock = new Mock(); collectionMock.Setup(c => c.Find(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cursorMock.Object); queryable = new MongoQuery(new MongoQueryProvider(collectionMock.Object)); } diff --git a/MongoDB.Linq/MongoLinqEx.cs b/MongoDB.Linq/MongoLinqEx.cs index 9865656b..2184bcd1 100644 --- a/MongoDB.Linq/MongoLinqEx.cs +++ b/MongoDB.Linq/MongoLinqEx.cs @@ -1,11 +1,11 @@ -using System; +using System; using MongoDB.Driver; namespace MongoDB.Linq { public static class MongoLinqEx { - public static IMongoQuery AsQueryable(this T collection) where T : IMongoCollection + public static IMongoQuery AsQueryable(this T collection) where T : IMongoCollection { return new MongoQuery(new MongoQueryProvider(collection)); } diff --git a/MongoDB.Linq/MongoQueryProvider.cs b/MongoDB.Linq/MongoQueryProvider.cs index c5f086e0..c8304f01 100644 --- a/MongoDB.Linq/MongoQueryProvider.cs +++ b/MongoDB.Linq/MongoQueryProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -13,9 +13,9 @@ private struct Result { public bool IsFirstCall; } - private readonly IMongoCollection collection; + private readonly IMongoCollection collection; - public MongoQueryProvider(IMongoCollection collection) + public MongoQueryProvider(IMongoCollection collection) { this.collection = collection; } diff --git a/MongoDB.Net-Tests/TestCollection.cs b/MongoDB.Net-Tests/TestCollection.cs index 32e95208..2200907b 100755 --- a/MongoDB.Net-Tests/TestCollection.cs +++ b/MongoDB.Net-Tests/TestCollection.cs @@ -18,14 +18,14 @@ public class TestCollection : MongoTestBase } public override void OnInit (){ - IMongoCollection finds = DB["finds"]; + IMongoCollection finds = DB["finds"]; for(int j = 1; j < 100; j++){ finds.Insert(new Document(){{"x", 4},{"h", "hi"},{"j", j}}); } for(int j = 100; j < 105; j++){ finds.Insert(new Document(){{"x", 4},{"n", 1},{"j", j}}); } - IMongoCollection charreads = DB["charreads"]; + IMongoCollection charreads = DB["charreads"]; charreads.Insert(new Document(){{"test", "1234" + pound + "56"}}); } @@ -64,7 +64,7 @@ public class TestCollection : MongoTestBase Document fields = new Document(); fields["x"] = 1; - ICursor c = DB["finds"].Find(query, -1, 0, fields); + ICursor c = DB["finds"].Find(query, -1, 0, fields); foreach(Document result in c.Documents){ Assert.IsNotNull(result); Assert.AreEqual(4, result["x"]); @@ -77,7 +77,7 @@ public class TestCollection : MongoTestBase Document query = new Document(); query["j"] = new Document().Add("$gt", 20); - ICursor c = DB["finds"].Find(query); + ICursor c = DB["finds"].Find(query); foreach(Document result in c.Documents){ Assert.IsNotNull(result); Object j = result["j"]; @@ -88,7 +88,7 @@ public class TestCollection : MongoTestBase [Test] public void TestManualWhere(){ Document query = new Document().Add("$where", new Code("this.j % 2 == 0")); - ICursor c = DB["finds"].Find(query); + ICursor c = DB["finds"].Find(query); foreach(Document result in c.Documents){ Assert.IsNotNull(result); Object j = result["j"]; @@ -97,7 +97,7 @@ public class TestCollection : MongoTestBase } [Test] public void TestFindWhereEquivalency(){ - IMongoCollection col = DB["finds"]; + IMongoCollection col = DB["finds"]; Document lt = new Document().Add("j", new Document().Add("$lt", 5)); string where = "this.j < 5"; Document explicitWhere = new Document().Add("$where", new Code(where)); @@ -110,7 +110,7 @@ public class TestCollection : MongoTestBase Assert.AreEqual(4, CountDocs(col.Find(funcDoc)), "Function where didn't return 4 docs"); } - private int CountDocs(ICursor cur) + private int CountDocs(ICursor cur) { int cnt = 0; foreach(Document doc in cur.Documents){ @@ -120,7 +120,7 @@ private int CountDocs(ICursor cur) } [Test] public void TestWhere(){ - ICursor c = DB["finds"].Find("this.j % 2 == 0"); + ICursor c = DB["finds"].Find("this.j % 2 == 0"); foreach(Document result in c.Documents){ Assert.IsNotNull(result); Object j = result["j"]; @@ -139,7 +139,7 @@ private int CountDocs(ICursor cur) [Test] public void TestSimpleInsert(){ - IMongoCollection inserts = DB["inserts"]; + IMongoCollection inserts = DB["inserts"]; Document indoc = new Document(); indoc["song"] = "Palmdale"; indoc["artist"] = "Afroman"; @@ -154,7 +154,7 @@ private int CountDocs(ICursor cur) [Test] public void TestReallySimpleInsert(){ - IMongoCollection inserts = DB["inserts"]; + IMongoCollection inserts = DB["inserts"]; Document indoc = new Document(); indoc["y"] = 1; indoc["x"] = 2; @@ -167,7 +167,7 @@ private int CountDocs(ICursor cur) [Test] public void TestPoundSymbolInsert(){ - IMongoCollection inserts = DB["inserts"]; + IMongoCollection inserts = DB["inserts"]; Document indoc = new Document().Add("x", "1234" + pound + "56").Add("y", 1); inserts.Insert(indoc); @@ -178,7 +178,7 @@ private int CountDocs(ICursor cur) [Test] public void TestArrayInsert(){ - IMongoCollection inserts = DB["inserts"]; + IMongoCollection inserts = DB["inserts"]; Document indoc1 = new Document(); indoc1["song"] = "The Axe"; indoc1["artist"] = "Tinsley Ellis"; @@ -203,7 +203,7 @@ private int CountDocs(ICursor cur) [Test] public void TestInsertOfArray(){ OidGenerator ogen = new OidGenerator(); - IMongoCollection inserts = DB["inserts"]; + IMongoCollection inserts = DB["inserts"]; Document album = new Document(); album["_id"] = ogen.Generate(); album["artist"] = "Popa Chubby"; @@ -227,7 +227,7 @@ private int CountDocs(ICursor cur) public void TestInsertLargerThan4MBDocument(){ Binary b = new Binary(new byte[1024 * 1024]); Document big = new Document(){{"name", "Big Document"}, {"b1", b}, {"b2", b}, {"b3", b}, {"b4", b}}; - IMongoCollection inserts = DB["inserts"]; + IMongoCollection inserts = DB["inserts"]; bool thrown = false; try{ inserts.Insert(big); @@ -242,7 +242,7 @@ private int CountDocs(ICursor cur) [Test] public void TestInsertBulkLargerThan4MBOfDocuments(){ Binary b = new Binary(new byte[1024 * 1024 * 2]); - IMongoCollection inserts = DB["inserts"]; + IMongoCollection inserts = DB["inserts"]; try{ Document[] docs = new Document[10]; //6MB+ of documents @@ -259,7 +259,7 @@ private int CountDocs(ICursor cur) [Test] public void TestDelete(){ - IMongoCollection deletes = DB["deletes"]; + IMongoCollection deletes = DB["deletes"]; Document doc = new Document(); doc["y"] = 1; doc["x"] = 2; @@ -279,7 +279,7 @@ private int CountDocs(ICursor cur) [Test] public void TestUpdateUpsertNotExisting(){ - IMongoCollection updates = DB["updates"]; + IMongoCollection updates = DB["updates"]; Document doc = new Document(); doc["First"] = "Sam"; doc["Last"] = "CorderNE"; @@ -293,7 +293,7 @@ private int CountDocs(ICursor cur) [Test] public void TestUpdateUpsertExisting(){ - IMongoCollection updates = DB["updates"]; + IMongoCollection updates = DB["updates"]; Document doc = new Document(); doc["First"] = "Mtt"; doc["Last"] = "Brewer"; @@ -317,14 +317,14 @@ private int CountDocs(ICursor cur) [Test] public void TestUpdateMany(){ - IMongoCollection updates = DB["updates"]; + IMongoCollection updates = DB["updates"]; updates.Insert(new Document().Add("Last", "Cordr").Add("First", "Sam")); updates.Insert(new Document().Add("Last", "Cordr").Add("First", "Sam2")); updates.Insert(new Document().Add("Last", "Cordr").Add("First", "Sam3")); Document selector = new Document().Add("Last", "Cordr"); - ICursor results = updates.Find(selector); + ICursor results = updates.Find(selector); bool found = false; foreach(Document doc in results.Documents){ Assert.AreEqual("Cordr", doc["Last"]); @@ -352,7 +352,7 @@ private int CountDocs(ICursor cur) [Test] public void TestUpdatePartial(){ - IMongoCollection updates = DB["updates"]; + IMongoCollection updates = DB["updates"]; int coolness = 5; Document einstein = new Document(){{"Last", "Einstien"},{"First", "Albert"},{"Coolness",coolness++}}; updates.Insert(einstein); @@ -368,7 +368,7 @@ private int CountDocs(ICursor cur) [Test] public void TestCount(){ - IMongoCollection counts = DB["counts"]; + IMongoCollection counts = DB["counts"]; int top = 100; for(int i = 0; i < top; i++){ counts.Insert(new Document().Add("Last", "Cordr").Add("First", "Sam").Add("cnt", i)); @@ -379,7 +379,7 @@ private int CountDocs(ICursor cur) [Test] public void TestCountWithSpec(){ - IMongoCollection counts = DB["counts_spec"]; + IMongoCollection counts = DB["counts_spec"]; counts.Insert(new Document().Add("Last", "Cordr").Add("First", "Sam").Add("cnt", 1)); counts.Insert(new Document().Add("Last", "Cordr").Add("First", "Sam").Add("cnt", 2)); counts.Insert(new Document().Add("Last", "Corder").Add("First", "Sam").Add("cnt", 3)); @@ -392,7 +392,7 @@ private int CountDocs(ICursor cur) [Test] public void TestCountInvalidCollection(){ - IMongoCollection counts = DB["counts_wtf"]; + IMongoCollection counts = DB["counts_wtf"]; Assert.AreEqual(0, counts.Count()); } } diff --git a/MongoDB.Net-Tests/TestCollectionMetaData.cs b/MongoDB.Net-Tests/TestCollectionMetaData.cs index c462d885..113cf625 100644 --- a/MongoDB.Net-Tests/TestCollectionMetaData.cs +++ b/MongoDB.Net-Tests/TestCollectionMetaData.cs @@ -18,7 +18,7 @@ public class TestCollectionMetaData : MongoTestBase } public override void OnInit (){ - IMongoCollection its = DB["indextests"]; + IMongoCollection its = DB["indextests"]; its.Insert(createDoc("S","A","Anderson","OH")); its.Insert(createDoc("T","B","Delhi","OH")); its.Insert(createDoc("F","B","Cincinnati","OH")); diff --git a/MongoDB.Net-Tests/TestCollectionSafeMode.cs b/MongoDB.Net-Tests/TestCollectionSafeMode.cs index 5c6d8088..05251cb7 100644 --- a/MongoDB.Net-Tests/TestCollectionSafeMode.cs +++ b/MongoDB.Net-Tests/TestCollectionSafeMode.cs @@ -18,7 +18,7 @@ public class TestCollectionSafeMode : MongoTestBase [Test] public void TestBadInsert(){ - IMongoCollection col = InitCollection("safeinsert"); + IMongoCollection col = InitCollection("safeinsert"); bool thrown = false; try{ col.Insert(new Document {{"x",1},{"y",2}},true); @@ -32,7 +32,7 @@ public class TestCollectionSafeMode : MongoTestBase [Test] public void TestBadUpdate(){ - IMongoCollection col = InitCollection("safeupdate"); + IMongoCollection col = InitCollection("safeupdate"); bool thrown = false; try{ col.Update(new Document {{"x", 1}}, new Document{{"x",2}},true); @@ -49,7 +49,7 @@ public class TestCollectionSafeMode : MongoTestBase [Test] public void TestMultiUpdate(){ - IMongoCollection col = InitCollection("safemupdate"); + IMongoCollection col = InitCollection("safemupdate"); Document newy = new Document(){{"y", 2}}; col.UpdateAll(newy, new Document(){{"y",1}},true); Assert.AreEqual(5, col.Count(newy)); @@ -68,9 +68,9 @@ public class TestCollectionSafeMode : MongoTestBase Assert.IsTrue(thrown, "Exception not thrown."); } - protected IMongoCollection InitCollection(string name) + protected IMongoCollection InitCollection(string name) { - IMongoCollection col = DB[name]; + IMongoCollection col = DB[name]; col.MetaData.CreateIndex(new Document{{"x", IndexOrder.Ascending}}, true); for(int x = 0; x < 5; x++){ col.Insert(new Document{{"x", x}, {"y", 1}}); diff --git a/MongoDB.Net-Tests/TestConcurrency.cs b/MongoDB.Net-Tests/TestConcurrency.cs index 67dd6a00..9e3a450e 100644 --- a/MongoDB.Net-Tests/TestConcurrency.cs +++ b/MongoDB.Net-Tests/TestConcurrency.cs @@ -22,7 +22,7 @@ public class TestConcurrency :MongoTestBase } public override void OnInit (){ - var col = (MongoCollection)DB["threadsmallreads"]; + var col = (IMongoCollection)DB["threadsmallreads"]; for(int j = 0; j < 4; j++){ col.Insert(new Document(){{"x", 4},{"j", j}}); } @@ -34,7 +34,7 @@ public class TestConcurrency :MongoTestBase Mongo db = new Mongo(); db.Connect(); - IMongoCollection col = DB["threadinserts"]; + IMongoCollection col = DB["threadinserts"]; List identifiers = new List{"A", "B", "C", "D"}; List threads = new List(); @@ -91,7 +91,7 @@ public class TestConcurrency :MongoTestBase Mongo db = new Mongo(); db.Connect(); - IMongoCollection col = DB["threadreadinserts"]; + IMongoCollection col = DB["threadreadinserts"]; List identifiers = new List{"A", "B", "C", "D"}; List colnames = new List{"threadsmallreads", "threadsmallreads", @@ -147,7 +147,7 @@ public class Inserter{ public int Iterations{get; set;} public int Count{get;set;} public String Identifier{get; set;} - public IMongoCollection Collection { get; set; } + public IMongoCollection Collection { get; set; } public void DoInserts(){ for(int x = 0; x < this.Iterations; x++){ @@ -165,12 +165,12 @@ public class Inserter{ public class Reader{ public int Iterations{get; set;} public int Count{get;set;} - public IMongoCollection Collection { get; set; } + public IMongoCollection Collection { get; set; } public void DoReads(){ for(int x = 0; x < this.Iterations; x++){ try{ - using(ICursor c = this.Collection.FindAll()) + using(ICursor c = this.Collection.FindAll()) { //Just read one and do nothing with the Document. foreach(Document d in c.Documents){ diff --git a/MongoDB.Net-Tests/TestCursor.cs b/MongoDB.Net-Tests/TestCursor.cs index ed2ab493..19cfcc35 100644 --- a/MongoDB.Net-Tests/TestCursor.cs +++ b/MongoDB.Net-Tests/TestCursor.cs @@ -18,13 +18,13 @@ public class TestCursor : MongoTestBase public override void OnInit (){ //smallreads - IMongoCollection smallreads = DB["smallreads"]; + IMongoCollection smallreads = DB["smallreads"]; for(int j = 1; j < 5; j++){ smallreads.Insert(new Document(){{"x", 4},{"j", j}}); } smallreads.Insert(new Document(){{"x", 4}, {"j", 5}, {"n", 1}}); - IMongoCollection reads = DB["reads"]; + IMongoCollection reads = DB["reads"]; for(int j = 1; j < 10000; j++){ reads.Insert(new Document(){{"x", 4},{"h", "hi"},{"j", j}}); } @@ -34,7 +34,7 @@ public class TestCursor : MongoTestBase [Test] public void TestCanReadSmall() { - ICursor c = DB["smallreads"].FindAll(); + ICursor c = DB["smallreads"].FindAll(); Assert.IsNotNull(c,"Cursor shouldn't be null"); int reads = 0; @@ -47,7 +47,7 @@ public void TestCanReadSmall() [Test] public void TestCanReadMore(){ - Cursor c = (Cursor)DB["reads"].FindAll(); + Cursor c = (Cursor)DB["reads"].FindAll(); Assert.IsNotNull(c,"Cursor shouldn't be null"); int reads = 0; @@ -70,7 +70,7 @@ public void TestCanReadSmall() [Test] public void TestCanReadAndKillCursor() { - var c = (Cursor)DB["reads"].FindAll(); + var c = (Cursor)DB["reads"].FindAll(); Assert.IsNotNull(c,"Cursor shouldn't be null"); foreach(Document doc in c.Documents){ @@ -82,7 +82,7 @@ public void TestCanReadAndKillCursor() [Test] public void TestCanLimit(){ - ICursor c = DB["reads"].FindAll().Limit(5); + ICursor c = DB["reads"].FindAll().Limit(5); Assert.IsNotNull(c,"Cursor shouldn't be null"); int reads = 0; @@ -95,7 +95,7 @@ public void TestCanReadAndKillCursor() [Test] public void TestSort(){ - IMongoCollection sorts = DB["sorts"]; + IMongoCollection sorts = DB["sorts"]; int[] randoms = new int[]{4,6,8,9,1,3,2,5,7,0}; foreach(int x in randoms){ sorts.Insert(new Document().Add("x", randoms[x])); @@ -125,7 +125,7 @@ public void TestCanReadAndKillCursor() [Test] public void TestHint(){ - IMongoCollection reads = DB["reads"]; + IMongoCollection reads = DB["reads"]; Document hint = new Document().Add("x",IndexOrder.Ascending); Document exp = reads.FindAll().Hint(hint).Explain(); diff --git a/MongoDB.Net-Tests/TestDatabase.cs b/MongoDB.Net-Tests/TestDatabase.cs index 3140f258..38b43e69 100644 --- a/MongoDB.Net-Tests/TestDatabase.cs +++ b/MongoDB.Net-Tests/TestDatabase.cs @@ -15,7 +15,7 @@ public class TestDatabase : MongoTestBase [Test] public void TestFollowReference(){ - IMongoCollection refs = DB["refs"]; + IMongoCollection refs = DB["refs"]; Oid id = new Oid("4a7067c30a57000000008ecb"); string msg = "this has an oid key"; Document doc = new Document(){{"_id", id},{"msg", msg}}; @@ -40,7 +40,7 @@ public class TestDatabase : MongoTestBase [Test] public void TestReferenceNonOid(){ - IMongoCollection refs = DB["refs"]; + IMongoCollection refs = DB["refs"]; Document doc = new Document().Add("_id",123).Add("msg", "this has a non oid key"); refs.Insert(doc); @@ -96,7 +96,7 @@ public class TestDatabase : MongoTestBase [Test] public void TestGetLastError(){ - IMongoCollection errcol = DB["errcol"]; + IMongoCollection errcol = DB["errcol"]; errcol.MetaData.CreateIndex(new Document(){{"x", IndexOrder.Ascending}}, true); Document dup = new Document(){{"x",1},{"y",2}}; errcol.Insert(dup); @@ -112,7 +112,7 @@ public class TestDatabase : MongoTestBase [Test] public void TestGetPrevError(){ - IMongoCollection col = DB["preverror"]; + IMongoCollection col = DB["preverror"]; col.MetaData.CreateIndex(new Document(){{"x", IndexOrder.Ascending}},true); List docs = new List(); for(int x = 0; x < 10; x++){ diff --git a/MongoDB.Net-Tests/TestDatabaseJavascript.cs b/MongoDB.Net-Tests/TestDatabaseJavascript.cs index 16a70cc1..ca7a7ffe 100644 --- a/MongoDB.Net-Tests/TestDatabaseJavascript.cs +++ b/MongoDB.Net-Tests/TestDatabaseJavascript.cs @@ -20,7 +20,7 @@ public class TestDatabaseJavascript : MongoTestBase DB["system.js"].Delete(new Document()); js = DB.Javascript; - IMongoCollection jsreads = DB["jsreads"]; + IMongoCollection jsreads = DB["jsreads"]; for(int j = 1; j < 10; j++){ jsreads.Insert(new Document(){{"j", j}}); } diff --git a/MongoDB.Net-Tests/TestMapReduce.cs b/MongoDB.Net-Tests/TestMapReduce.cs index 89830d28..0f8cfc81 100644 --- a/MongoDB.Net-Tests/TestMapReduce.cs +++ b/MongoDB.Net-Tests/TestMapReduce.cs @@ -7,7 +7,7 @@ namespace MongoDB.Driver [TestFixture()] public class TestMapReduce : MongoTestBase { - IMongoCollection mrcol; + IMongoCollection mrcol; string mapfunction = "function(){\n" + " this.tags.forEach(\n" + " function(z){\n" + diff --git a/MongoDB.Net-Tests/TestMapReduceBuilder.cs b/MongoDB.Net-Tests/TestMapReduceBuilder.cs index abe02cd3..c7e3d535 100644 --- a/MongoDB.Net-Tests/TestMapReduceBuilder.cs +++ b/MongoDB.Net-Tests/TestMapReduceBuilder.cs @@ -9,7 +9,7 @@ namespace MongoDB.Driver [TestFixture()] public class TestMapReduceBuilder : MongoTestBase { - IMongoCollection mrcol; + IMongoCollection mrcol; string mapfunction = "function(){\n" + " this.tags.forEach(\n" + " function(z){\n" + diff --git a/MongoDBDriver/Cursor.cs b/MongoDBDriver/Cursor.cs index 53b83122..1a93a95f 100644 --- a/MongoDBDriver/Cursor.cs +++ b/MongoDBDriver/Cursor.cs @@ -7,17 +7,16 @@ namespace MongoDB.Driver { - public class Cursor : ICursor - where T : class + public class Cursor : ICursor { private readonly Connection _connection; private readonly Document _specOpts = new Document(); private bool _isModifiable = true; - private object _spec; - private object _fields; + private Document _spec; + private Document _fields; private int _limit; private QueryOptions _options; - private ReplyMessage _reply; + private ReplyMessage _reply; private int _skip; private readonly ISerializationFactory _serializationFactory = SerializationFactory.Default; @@ -38,11 +37,8 @@ public class Cursor : ICursor /// /// The conn. /// Full name of the collection. - /// The spec. - /// The limit. - /// The skip. - /// The fields. - public Cursor(Connection connection, string fullCollectionName, object spec, int limit, int skip, object fields) + [Obsolete("Use Cursor(Connection, fullCollectionName) and then call the Spec, Limit, Skip and Fields methods")] + public Cursor(Connection connection, string fullCollectionName, Document spec, int limit, int skip, Document fields) : this(connection, fullCollectionName){ //Todo: should be internal if(spec == null) @@ -70,16 +66,7 @@ public Cursor(Connection connection, string fullCollectionName, object spec, int /// /// The spec. /// - public ICursor Spec(Document spec){ - return Spec((object)spec); - } - - /// - /// Specs the specified spec. - /// - /// The spec. - /// - public ICursor Spec(object spec){ + public ICursor Spec(Document spec){ TryModify(); _spec = spec; return this; @@ -90,7 +77,7 @@ public Cursor(Connection connection, string fullCollectionName, object spec, int /// /// The limit. /// - public ICursor Limit(int limit){ + public ICursor Limit(int limit){ TryModify(); _limit = limit; return this; @@ -101,87 +88,61 @@ public Cursor(Connection connection, string fullCollectionName, object spec, int /// /// The skip. /// - public ICursor Skip(int skip){ + public ICursor Skip(int skip){ TryModify(); _skip = skip; return this; } /// - /// Fieldses the specified fields. - /// - /// The fields. - /// - public ICursor Fields(Document fields){ - return Fields((object)fields); - } - - /// - /// Fieldses the specified fields. + /// Limits the returned documents to the specified fields /// /// The fields. /// - public ICursor Fields(object fields){ + public ICursor Fields(Document fields){ TryModify(); _fields = fields; return this; } /// - /// Sorts the specified field. + /// Sorts the specified ascending on the specified field name. /// /// The field. /// - public ICursor Sort(string field){ + public ICursor Sort(string field){ return Sort(field, IndexOrder.Ascending); } /// - /// Sorts the specified field. + /// Sorts on the specified field. /// /// The field. /// The order. /// - public ICursor Sort(string field, IndexOrder order){ + public ICursor Sort(string field, IndexOrder order){ return Sort(new Document().Add(field, order)); } /// - /// Sorts the specified fields. - /// - /// The fields. - /// - public ICursor Sort(Document fields){ - return Sort((object)fields); - } - - /// - /// Sorts the specified fields. + /// Document containing the fields to sort on and the order (ascending/descending) /// /// The fields. /// - public ICursor Sort(object fields) + public ICursor Sort(Document fields) { TryModify(); AddOrRemoveSpecOpt("$orderby", fields); return this; } - /// - /// Hints the specified index. - /// - /// The index. - /// - public ICursor Hint(Document index){ - return Hint((object)index); - } /// - /// Hints the specified index. + /// Hint to use the specified index. /// /// The index. /// - public ICursor Hint(object index) + public ICursor Hint(Document index) { TryModify(); AddOrRemoveSpecOpt("$hint", index); @@ -189,23 +150,16 @@ public ICursor Hint(object index) } /// - /// Snapshots the specified index. + /// Snapshot mode assures that objects which update during the lifetime of a query are returned once + /// and only once. This is most important when doing a find-and-update loop that changes the size of + /// documents that are returned ($inc does not change size). /// /// The index. - /// - public ICursor Snapshot(Document index){ - return Snapshot((object)index); - } - - /// - /// Snapshots the specified index. - /// - /// The index. - /// - public ICursor Snapshot(object index) - { + /// Because snapshot mode traverses the _id index, it may not be used with sorting or + /// explicit hints. It also cannot use any other index for the query. + public ICursor Snapshot(){ TryModify(); - AddOrRemoveSpecOpt("$snapshot", index); + AddOrRemoveSpecOpt("$snapshot", true); return this; } @@ -213,8 +167,7 @@ public ICursor Snapshot(object index) /// Explains this instance. /// /// - public T Explain(){ - //Todo: i am not sure that this will work now. + public Document Explain(){ TryModify(); _specOpts["$explain"] = true; @@ -240,7 +193,7 @@ public ICursor Snapshot(object index) /// Gets the documents. /// /// The documents. - public IEnumerable Documents{ + public IEnumerable Documents{ get{ if(_reply == null) RetrieveData(); @@ -295,7 +248,7 @@ public ICursor Snapshot(object index) /// /// The options. /// - public ICursor Options(QueryOptions options){ + public ICursor Options(QueryOptions options){ TryModify(); _options = options; return this; @@ -305,9 +258,9 @@ public ICursor Snapshot(object index) /// Retrieves the data. /// private void RetrieveData(){ - var descriptor = _serializationFactory.GetBsonDescriptor(typeof(T), _connection); + var descriptor = _serializationFactory.GetBsonDescriptor(typeof(Document), _connection); - var query = new QueryMessage(descriptor){ + var query = new QueryMessage(descriptor){ FullCollectionName = FullCollectionName, Query = BuildSpec(), NumberToReturn = _limit, @@ -318,10 +271,10 @@ public ICursor Snapshot(object index) if(_fields != null) query.ReturnFieldSelector = _fields; - var builder = _serializationFactory.GetBsonBuilder(typeof(T), _connection); + var builder = _serializationFactory.GetBsonBuilder(typeof(Document), _connection); try{ - _reply = _connection.SendTwoWayMessage(query, builder); + _reply = _connection.SendTwoWayMessage(query, builder); Id = _reply.CursorId; if(_limit < 0) _limit = _limit*-1; @@ -338,10 +291,10 @@ public ICursor Snapshot(object index) private void RetrieveMoreData(){ var getMoreMessage = new GetMoreMessage(FullCollectionName, Id, _limit); - var builder = _serializationFactory.GetBsonBuilder(typeof(T), _connection); + var builder = _serializationFactory.GetBsonBuilder(typeof(Document), _connection); try{ - _reply = _connection.SendTwoWayMessage(getMoreMessage, builder); + _reply = _connection.SendTwoWayMessage(getMoreMessage, builder); Id = _reply.CursorId; } catch(IOException exception){ diff --git a/MongoDBDriver/DatabaseJavascript.cs b/MongoDBDriver/DatabaseJavascript.cs index d7da887a..948f10c2 100644 --- a/MongoDBDriver/DatabaseJavascript.cs +++ b/MongoDBDriver/DatabaseJavascript.cs @@ -10,7 +10,7 @@ public class DatabaseJavascript : ICollection { //private Connection connection; private MongoDatabase db; - private IMongoCollection js; + private IMongoCollection js; internal DatabaseJavascript (MongoDatabase db){ this.db = db; diff --git a/MongoDBDriver/DatabaseMetaData.cs b/MongoDBDriver/DatabaseMetaData.cs index cd0ef09f..e9d6ddb8 100644 --- a/MongoDBDriver/DatabaseMetaData.cs +++ b/MongoDBDriver/DatabaseMetaData.cs @@ -18,20 +18,20 @@ public class DatabaseMetaData this.db = new MongoDatabase(conn, name); } - public MongoCollection CreateCollection(String name){ + public IMongoCollection CreateCollection(String name){ return this.CreateCollection(name,null); } - public MongoCollection CreateCollection(String name, Document options) + public IMongoCollection CreateCollection(String name, Document options) { Document cmd = new Document(); cmd.Add("create", name).Merge(options); db.SendCommand(cmd); - return new MongoCollection(connection, this.name, name); + return new MongoCollection(connection, this.name, name); } - public Boolean DropCollection(MongoCollection col) + public Boolean DropCollection(MongoCollection col) { return this.DropCollection(col.Name); } @@ -42,12 +42,12 @@ public Boolean DropCollection(MongoCollection col) } public Boolean DropDatabase(){ - Document result = db.SendCommand("dropDatabase"); - return result.Contains("ok") && ((double)result["ok"] == 1); + Document result = db.SendCommand("dropDatabase"); + return result.Contains("ok") && ((double)result["ok"] == 1); } public void AddUser(string username, string password){ - IMongoCollection users = db["system.users"]; + IMongoCollection users = db["system.users"]; string pwd = MongoDatabase.Hash(username + ":mongo:" + password); Document user = new Document().Add("user", username).Add("pwd", pwd); @@ -58,12 +58,12 @@ public Boolean DropCollection(MongoCollection col) } public void RemoveUser(string username){ - IMongoCollection users = db["system.users"]; + IMongoCollection users = db["system.users"]; users.Delete(new Document().Add("user", username)); } - public ICursor ListUsers(){ - IMongoCollection users = db["system.users"]; + public ICursor ListUsers(){ + IMongoCollection users = db["system.users"]; return users.FindAll(); } diff --git a/MongoDBDriver/Generic/Cursor.cs b/MongoDBDriver/Generic/Cursor.cs new file mode 100644 index 00000000..15017959 --- /dev/null +++ b/MongoDBDriver/Generic/Cursor.cs @@ -0,0 +1,388 @@ +using System; +using System.Collections.Generic; +using System.IO; +using MongoDB.Driver.Connections; +using MongoDB.Driver.Protocol; +using MongoDB.Driver.Serialization; + +namespace MongoDB.Driver.Generic +{ + public class Cursor : ICursor + where T : class + { + private readonly Connection _connection; + private readonly Document _specOpts = new Document(); + private bool _isModifiable = true; + private object _spec; + private object _fields; + private int _limit; + private QueryOptions _options; + private ReplyMessage _reply; + private int _skip; + private readonly ISerializationFactory _serializationFactory = SerializationFactory.Default; + + /// + /// Initializes a new instance of the class. + /// + /// The conn. + /// Full name of the collection. + public Cursor(Connection connection, string fullCollectionName){ + //Todo: should be internal + Id = -1; + _connection = connection; + FullCollectionName = fullCollectionName; + } + + /// + /// Initializes a new instance of the class. + /// + /// The conn. + /// Full name of the collection. + /// The spec. + /// The limit. + /// The skip. + /// The fields. + public Cursor(Connection connection, string fullCollectionName, object spec, int limit, int skip, object fields) + : this(connection, fullCollectionName){ + //Todo: should be internal + if(spec == null) + spec = new Document(); + _spec = spec; + _limit = limit; + _skip = skip; + _fields = fields; + } + + /// + /// Gets or sets the full name of the collection. + /// + /// The full name of the collection. + public string FullCollectionName { get; private set; } + + /// + /// Gets or sets the id. + /// + /// The id. + public long Id { get; private set; } + + /// + /// Specs the specified spec. + /// + /// The spec. + /// + public ICursor Spec(Document spec){ + return Spec((object)spec); + } + + /// + /// Specs the specified spec. + /// + /// The spec. + /// + public ICursor Spec(object spec){ + TryModify(); + _spec = spec; + return this; + } + + /// + /// Limits the specified limit. + /// + /// The limit. + /// + public ICursor Limit(int limit){ + TryModify(); + _limit = limit; + return this; + } + + /// + /// Skips the specified skip. + /// + /// The skip. + /// + public ICursor Skip(int skip){ + TryModify(); + _skip = skip; + return this; + } + + /// + /// Fieldses the specified fields. + /// + /// The fields. + /// + public ICursor Fields(Document fields){ + return Fields((object)fields); + } + + /// + /// Fieldses the specified fields. + /// + /// The fields. + /// + public ICursor Fields(object fields){ + TryModify(); + _fields = fields; + return this; + } + + /// + /// Sorts the specified field. + /// + /// The field. + /// + public ICursor Sort(string field){ + return Sort(field, IndexOrder.Ascending); + } + + /// + /// Sorts the specified field. + /// + /// The field. + /// The order. + /// + public ICursor Sort(string field, IndexOrder order){ + return Sort(new Document().Add(field, order)); + } + + /// + /// Sorts the specified fields. + /// + /// The fields. + /// + public ICursor Sort(Document fields){ + return Sort((object)fields); + } + + /// + /// Sorts the specified fields. + /// + /// The fields. + /// + public ICursor Sort(object fields) + { + TryModify(); + AddOrRemoveSpecOpt("$orderby", fields); + return this; + } + + /// + /// Hints the specified index. + /// + /// The index. + /// + public ICursor Hint(Document index){ + return Hint((object)index); + } + + /// + /// Hints the specified index. + /// + /// The index. + /// + public ICursor Hint(object index) + { + TryModify(); + AddOrRemoveSpecOpt("$hint", index); + return this; + } + + /// + /// Snapshots the specified index. + /// + /// The index. + /// + public ICursor Snapshot(Document index){ + return Snapshot((object)index); + } + + /// + /// Snapshots the specified index. + /// + /// The index. + /// + public ICursor Snapshot(object index) + { + TryModify(); + AddOrRemoveSpecOpt("$snapshot", index); + return this; + } + + /// + /// Explains this instance. + /// + /// + public T Explain(){ + //Todo: i am not sure that this will work now. + TryModify(); + _specOpts["$explain"] = true; + + var documents = Documents; + + using((IDisposable)documents){ + foreach(var document in documents) + return document; + } + + throw new InvalidOperationException("Explain failed."); + } + + /// + /// Gets a value indicating whether this is modifiable. + /// + /// true if modifiable; otherwise, false. + public bool IsModifiable{ + get { return _isModifiable; } + } + + /// + /// Gets the documents. + /// + /// The documents. + public IEnumerable Documents{ + get{ + if(_reply == null) + RetrieveData(); + if(_reply == null) + throw new InvalidOperationException("Expecting reply but get null"); + + var documents = _reply.Documents; + var documentCount = 0; + var shouldBreak = false; + + while(!shouldBreak){ + foreach(var document in documents) + if((_limit == 0) || (_limit != 0 && documentCount < _limit)){ + documentCount++; + yield return document; + } + else + yield break; + + if(Id != 0){ + RetrieveMoreData(); + documents = _reply.Documents; + if(documents == null) + shouldBreak = true; + } + else + shouldBreak = true; + } + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose(){ + if(Id == 0) //All server side resources disposed of. + return; + + var killCursorsMessage = new KillCursorsMessage(Id); + + try{ + _connection.SendMessage(killCursorsMessage); + Id = 0; + } + catch(IOException exception){ + throw new MongoCommException("Could not read data, communication failure", _connection, exception); + } + } + + /// + /// Optionses the specified options. + /// + /// The options. + /// + public ICursor Options(QueryOptions options){ + TryModify(); + _options = options; + return this; + } + + /// + /// Retrieves the data. + /// + private void RetrieveData(){ + var descriptor = _serializationFactory.GetBsonDescriptor(typeof(T), _connection); + + var query = new QueryMessage(descriptor){ + FullCollectionName = FullCollectionName, + Query = BuildSpec(), + NumberToReturn = _limit, + NumberToSkip = _skip, + Options = _options + }; + + if(_fields != null) + query.ReturnFieldSelector = _fields; + + var builder = _serializationFactory.GetBsonBuilder(typeof(T), _connection); + + try{ + _reply = _connection.SendTwoWayMessage(query, builder); + Id = _reply.CursorId; + if(_limit < 0) + _limit = _limit*-1; + _isModifiable = false; + } + catch(IOException exception){ + throw new MongoCommException("Could not read data, communication failure", _connection, exception); + } + } + + /// + /// Retrieves the more data. + /// + private void RetrieveMoreData(){ + var getMoreMessage = new GetMoreMessage(FullCollectionName, Id, _limit); + + var builder = _serializationFactory.GetBsonBuilder(typeof(T), _connection); + + try{ + _reply = _connection.SendTwoWayMessage(getMoreMessage, builder); + Id = _reply.CursorId; + } + catch(IOException exception){ + Id = 0; + throw new MongoCommException("Could not read data, communication failure", _connection, exception); + } + } + + /// + /// Tries the modify. + /// + private void TryModify(){ + if(_isModifiable) + return; + throw new InvalidOperationException("Cannot modify a cursor that has already returned documents."); + } + + /// + /// Adds the or remove spec opt. + /// + /// The key. + /// The doc. + private void AddOrRemoveSpecOpt(string key, object doc){ + if(doc == null) + _specOpts.Remove(key); + else + _specOpts[key] = doc; + } + + /// + /// Builds the spec. + /// + /// + private object BuildSpec(){ + if(_specOpts.Count == 0) + return _spec; + + var document = new Document(); + _specOpts.CopyTo(document); + document["$query"] = _spec; + return document; + } + } +} \ No newline at end of file diff --git a/MongoDBDriver/Generic/ICursor.cs b/MongoDBDriver/Generic/ICursor.cs new file mode 100644 index 00000000..b80fcad9 --- /dev/null +++ b/MongoDBDriver/Generic/ICursor.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace MongoDB.Driver.Generic { + public interface ICursor : IDisposable + { + ICursor Spec(Document spec); + ICursor Spec(object spec); + ICursor Limit(int limit); + ICursor Skip(int skip); + ICursor Fields(Document fields); + ICursor Fields(object fields); + ICursor Sort(string field); + ICursor Sort(string field, IndexOrder order); + ICursor Sort(Document fields); + ICursor Sort(object fields); + ICursor Hint(Document index); + ICursor Hint(object index); + ICursor Snapshot(Document index); + ICursor Snapshot(object index); + T Explain(); + bool IsModifiable { get; } + IEnumerable Documents { get; } + } +} diff --git a/MongoDBDriver/Generic/IMongoCollection.cs b/MongoDBDriver/Generic/IMongoCollection.cs new file mode 100644 index 00000000..13db49c3 --- /dev/null +++ b/MongoDBDriver/Generic/IMongoCollection.cs @@ -0,0 +1,396 @@ +using System; +using System.Collections.Generic; + +namespace MongoDB.Driver.Generic +{ + public interface IMongoCollection where T : class + { + /// + /// Gets the database. + /// + /// The database. + MongoDatabase Database { get; } + + /// + /// Gets or sets the name. + /// + /// The name. + string Name { get; } + + /// + /// Gets or sets the name of the database. + /// + /// The name of the database. + string DatabaseName { get; } + + /// + /// Gets the full name including database name. + /// + /// The full name. + string FullName { get; } + + /// + /// Gets the meta data. + /// + /// The meta data. + CollectionMetaData MetaData { get; } + + /// + /// Finds and returns the first document in a query. + /// + /// A representing the query. + /// + /// A from the collection. + /// + T FindOne(Document spec); + + /// + /// Finds and returns the first document in a query. + /// + /// A representing the query. + /// + /// A from the collection. + /// + T FindOne(object spec); + + /// + /// Finds all. + /// + /// + ICursor FindAll(); + + /// + /// Finds the specified where. + /// + /// The where. + /// + ICursor Find(String where); + + /// + /// Finds the specified spec. + /// + /// The spec. + /// + ICursor Find(Document spec); + + /// + /// Finds the specified spec. + /// + /// The spec. + /// + ICursor Find(object spec); + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// + ICursor Find(Document spec, int limit, int skip); + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// + ICursor Find(object spec, int limit, int skip); + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// The fields. + /// + ICursor Find(Document spec, int limit, int skip, Document fields); + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// The fields. + /// + ICursor Find(object spec, int limit, int skip, object fields); + + /// + /// Entrypoint into executing a map/reduce query against the collection. + /// + /// + MapReduce MapReduce(); + + /// + /// Maps the reduce builder. + /// + /// + MapReduceBuilder MapReduceBuilder(); + + /// + /// Count all items in the collection. + /// + long Count(); + + /// + /// Count all items in a collection that match the query spec. + /// + /// The spec. + /// + /// + /// It will return 0 if the collection doesn't exist yet. + /// + long Count(Document spec); + + /// + /// Count all items in a collection that match the query spec. + /// + /// The spec. + /// + /// + /// It will return 0 if the collection doesn't exist yet. + /// + long Count(object spec); + + /// + /// Inserts the Document into the collection. + /// + void Insert(Document document, bool safemode); + + /// + /// Inserts the Document into the collection. + /// + void Insert(object document, bool safemode); + + /// + /// Inserts the specified doc. + /// + /// The doc. + void Insert(Document document); + + /// + /// Inserts the specified doc. + /// + /// The doc. + void Insert(object document); + + /// + /// Inserts the specified documents. + /// + /// The documents. + /// if set to true [safemode]. + void Insert(IEnumerable documents, bool safemode); + + /// + /// Inserts the specified documents. + /// + /// The documents. + /// if set to true [safemode]. + void Insert(IEnumerable documents, bool safemode); + + /// + /// Inserts the specified documents. + /// + /// The documents. + void Insert(IEnumerable documents); + + /// + /// Inserts the specified documents. + /// + /// The documents. + void Insert(IEnumerable documents); + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// if set to true [safemode]. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + void Delete(Document selector, bool safemode); + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// if set to true [safemode]. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + void Delete(object selector, bool safemode); + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + void Delete(Document selector); + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + void Delete(object selector); + + /// + /// Updates the specified document. + /// + /// The document. + /// if set to true [safemode]. + void Update(Document document, bool safemode); + + /// + /// Updates the specified document. + /// + /// The document. + /// if set to true [safemode]. + void Update(object document, bool safemode); + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// + /// _id will be used in the document to create a selector. If it isn't in + /// the document then it is assumed that the document is new and an upsert is sent to the database + /// instead. + /// + void Update(Document document); + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// + /// _id will be used in the document to create a selector. If it isn't in + /// the document then it is assumed that the document is new and an upsert is sent to the database + /// instead. + /// + void Update(object document); + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + void Update(Document document, Document selector, bool safemode); + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + void Update(object document, object selector, bool safemode); + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// The selector. + void Update(Document document, Document selector); + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// The selector. + void Update(object document, object selector); + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// The flags. + /// if set to true [safemode]. + void Update(Document document, Document selector, UpdateFlags flags, bool safemode); + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// The flags. + /// if set to true [safemode]. + void Update(object document, object selector, UpdateFlags flags, bool safemode); + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The to update with + /// The query spec to find the document to update. + /// + void Update(Document document, Document selector, UpdateFlags flags); + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The to update with + /// The query spec to find the document to update. + /// + void Update(object document, object selector, UpdateFlags flags); + + /// + /// Runs a multiple update query against the database. It will wrap any + /// doc with $set if the passed in doc doesn't contain any '$' ops. + /// + /// The document. + /// The selector. + void UpdateAll(Document document, Document selector); + + /// + /// Runs a multiple update query against the database. It will wrap any + /// doc with $set if the passed in doc doesn't contain any '$' ops. + /// + /// The document. + /// The selector. + void UpdateAll(object document, object selector); + + /// + /// Updates all. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + void UpdateAll(Document document, Document selector, bool safemode); + + /// + /// Updates all. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + void UpdateAll(object document, object selector, bool safemode); + + /// + /// Saves a document to the database using an upsert. + /// + /// The document. + /// + /// The document will contain the _id that is saved to the database. This is really just an alias + /// to Update(Document) to maintain consistency between drivers. + /// + void Save(Document document); + + /// + /// Saves a document to the database using an upsert. + /// + /// The document. + /// + /// The document will contain the _id that is saved to the database. This is really just an alias + /// to Update(Document) to maintain consistency between drivers. + /// + void Save(object document); + } +} \ No newline at end of file diff --git a/MongoDBDriver/Generic/MongoCollection.cs b/MongoDBDriver/Generic/MongoCollection.cs new file mode 100644 index 00000000..cb21d984 --- /dev/null +++ b/MongoDBDriver/Generic/MongoCollection.cs @@ -0,0 +1,701 @@ +using System; +using System.Collections.Generic; +using System.IO; +using MongoDB.Driver.Connections; +using MongoDB.Driver.Protocol; +using MongoDB.Driver.Serialization; + +namespace MongoDB.Driver.Generic +{ + /// + /// + /// + public class MongoCollection : IMongoCollection + where T : class + { + private readonly Connection _connection; + private MongoDatabase _database; + private CollectionMetaData _metaData; + private readonly ISerializationFactory _serializationFactory = SerializationFactory.Default; + + /// + /// Initializes a new instance of the class. + /// + /// The connection. + /// Name of the database. + /// The name. + public MongoCollection(Connection connection, string databaseName, string name){ + //Todo: This should be internal + Name = name; + DatabaseName = databaseName; + _connection = connection; + } + + /// + /// Gets the database. + /// + /// The database. + public MongoDatabase Database{ + get { return _database ?? (_database = new MongoDatabase(_connection, DatabaseName)); } + } + + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; private set; } + + /// + /// Gets or sets the name of the database. + /// + /// The name of the database. + public string DatabaseName { get; private set; } + + /// + /// Gets the full name including database name. + /// + /// The full name. + public string FullName{ + get { return DatabaseName + "." + Name; } + } + + /// + /// Gets the meta data. + /// + /// The meta data. + public CollectionMetaData MetaData{ + get { return _metaData ?? (_metaData = new CollectionMetaData(DatabaseName, Name, _connection)); } + } + + /// + /// Finds and returns the first document in a query. + /// + /// A representing the query. + /// + /// A from the collection. + /// + public T FindOne(Document spec) + { + return FindOne((object)spec); + } + + /// + /// Finds and returns the first document in a query. + /// + /// A representing the query. + /// + /// A from the collection. + /// + public T FindOne(object spec) + { + var cursor = Find(spec, -1, 0, null); + foreach(var document in cursor.Documents) + { + cursor.Dispose(); + return document; + } + //FIXME Decide if this should throw a not found exception instead of returning null. + return null; //this.Find(spec, -1, 0, null)[0]; + } + + /// + /// Finds all. + /// + /// + public ICursor FindAll() + { + var spec = new Document(); + return Find(spec, 0, 0, null); + } + + /// + /// Finds the specified where. + /// + /// The where. + /// + public ICursor Find(String where) + { + var spec = new Document{{"$where", new Code(where)}}; + return Find(spec, 0, 0, null); + } + + /// + /// Finds the specified spec. + /// + /// The spec. + /// + public ICursor Find(Document spec) + { + return Find((object)spec); + } + + /// + /// Finds the specified spec. + /// + /// The spec. + /// + public ICursor Find(object spec) + { + return Find(spec, 0, 0, null); + } + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// + public ICursor Find(Document spec, int limit, int skip) + { + return Find((object)spec, limit, skip, null); + } + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// + public ICursor Find(object spec, int limit, int skip) + { + return Find(spec, limit, skip, null); + } + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// The fields. + /// + public ICursor Find(Document spec, int limit, int skip, Document fields) + { + return Find((object)spec, limit, skip, (object)fields); + } + + /// + /// Finds the specified spec. + /// + /// The spec. + /// The limit. + /// The skip. + /// The fields. + /// + public ICursor Find(object spec, int limit, int skip, object fields) + { + if(spec == null) + spec = new Document(); + return new Cursor(_connection, FullName, spec, limit, skip, fields); + } + + /// + /// Entrypoint into executing a map/reduce query against the collection. + /// + /// A + public MapReduce MapReduce(){ + return new MapReduce(Database, Name); + } + + /// + /// Maps the reduce builder. + /// + /// + public MapReduceBuilder MapReduceBuilder(){ + return new MapReduceBuilder(MapReduce()); + } + + /// + /// Count all items in the collection. + /// + public long Count(){ + return Count(new Document()); + } + + /// + /// Count all items in a collection that match the query spec. + /// + /// The spec. + /// + /// + /// It will return 0 if the collection doesn't exist yet. + /// + public long Count(Document spec){ + return Count((object)spec); + } + + /// + /// Count all items in a collection that match the query spec. + /// + /// The spec. + /// + /// + /// It will return 0 if the collection doesn't exist yet. + /// + public long Count(object spec) + { + try + { + var response = Database.SendCommand(new Document().Add("count", Name).Add("query", spec)); + return Convert.ToInt64((double)response["n"]); + } + catch(MongoCommandException) + { + //FIXME This is an exception condition when the namespace is missing. + //-1 might be better here but the console returns 0. + return 0; + } + } + + /// + /// Inserts the Document into the collection. + /// + public void Insert(Document document, bool safemode){ + Insert((object)document,safemode); + } + + /// + /// Inserts the Document into the collection. + /// + public void Insert(object document, bool safemode) + { + Insert(document); + CheckError(safemode); + } + + /// + /// Inserts the specified doc. + /// + /// The doc. + public void Insert(Document document){ + Insert((object)document); + } + + /// + /// Inserts the specified doc. + /// + /// The doc. + public void Insert(object document) + { + Insert(new[] { document }); + } + + /// + /// Inserts the specified documents. + /// + /// The documents. + /// if set to true [safemode]. + public void Insert(IEnumerable documents, bool safemode) + { + Insert((IEnumerable)documents, safemode); + } + + /// + /// Inserts the specified documents. + /// + /// The documents. + /// if set to true [safemode]. + public void Insert(IEnumerable documents, bool safemode) + { + if(safemode) + Database.ResetError(); + Insert(documents); + CheckPreviousError(safemode); + } + + /// + /// Inserts the specified documents. + /// + /// The documents. + public void Insert(IEnumerable documents){ + Insert(documents); + } + + /// + /// Inserts the specified documents. + /// + /// The documents. + public void Insert(IEnumerable documents) + { + var insertMessage = new InsertMessage + { + FullCollectionName = FullName + }; + + var insertDocument = new List(); + var descriotor = _serializationFactory.GetObjectDescriptor(typeof(T)); + + foreach(var document in documents) + { + var id = descriotor.GetPropertyValue(document, "_id"); + + if(id == null) + descriotor.SetPropertyValue(document, "_id", Oid.NewOid()); + + insertDocument.Add(document); + } + + insertMessage.Documents = insertDocument.ToArray(); + + try + { + _connection.SendMessage(insertMessage); + } + catch(IOException exception) + { + throw new MongoCommException("Could not insert document, communication failure", _connection, exception); + } + } + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// if set to true [safemode]. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + public void Delete(Document selector, bool safemode){ + Delete((object)selector, safemode); + } + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// if set to true [safemode]. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + public void Delete(object selector, bool safemode) + { + Delete(selector); + CheckError(safemode); + } + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + public void Delete(Document selector){ + Delete((object)selector); + } + + /// + /// Deletes documents from the collection according to the spec. + /// + /// The selector. + /// + /// An empty document will match all documents in the collection and effectively truncate it. + /// + public void Delete(object selector) + { + var descriptor = _serializationFactory.GetBsonDescriptor(typeof(T),_connection); + + var deleteMessage = new DeleteMessage(descriptor) + { + FullCollectionName = FullName, + Selector = selector + }; + + try + { + _connection.SendMessage(deleteMessage); + } + catch(IOException exception) + { + throw new MongoCommException("Could not delete document, communication failure", _connection, exception); + } + } + + /// + /// Updates the specified document. + /// + /// The document. + /// if set to true [safemode]. + public void Update(Document document, bool safemode){ + Update((object)document,safemode); + } + + /// + /// Updates the specified document. + /// + /// The document. + /// if set to true [safemode]. + public void Update(object document, bool safemode) + { + Update(document); + CheckError(safemode); + } + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// + /// _id will be used in the document to create a selector. If it isn't in + /// the document then it is assumed that the document is new and an upsert is sent to the database + /// instead. + /// + public void Update(Document document) + { + Update((object)document); + } + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// + /// _id will be used in the document to create a selector. If it isn't in + /// the document then it is assumed that the document is new and an upsert is sent to the database + /// instead. + /// + public void Update(object document) + { + //Try to generate a selector using _id for an existing document. + //otherwise just set the upsert flag to 1 to insert and send onward. + var selector = new Document(); + var upsert = UpdateFlags.Upsert; + + var descriptor = _serializationFactory.GetObjectDescriptor(typeof(T)); + + var value = descriptor.GetPropertyValue(document, "_id"); + + if(value!=null){ + selector["_id"] = value; + }else{ + //Likely a new document + descriptor.SetPropertyValue(document,"_id",Oid.NewOid()); + upsert = UpdateFlags.Upsert; + } + + Update(document, selector, upsert); + } + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + public void Update(Document document, Document selector, bool safemode) + { + Update((object)document, (object)selector, 0, safemode); + //Update((object)document, (object)document, safemode); + } + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + public void Update(object document, object selector, bool safemode) + { + Update(document, selector, 0, safemode); + } + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// The selector. + public void Update(Document document, Document selector) + { + Update((object)document, (object)selector); + } + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The document. + /// The selector. + public void Update(object document, object selector) + { + Update(document, selector, 0); + } + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// The flags. + /// if set to true [safemode]. + public void Update(Document document, Document selector, UpdateFlags flags, bool safemode) + { + Update((object)document, (object)selector, flags, safemode); + } + + /// + /// Updates the specified document. + /// + /// The document. + /// The selector. + /// The flags. + /// if set to true [safemode]. + public void Update(object document, object selector, UpdateFlags flags, bool safemode) + { + Update(document, selector, flags); + CheckError(safemode); + } + + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The to update with + /// The query spec to find the document to update. + /// + public void Update(Document document, Document selector, UpdateFlags flags) + { + Update((object)document, (object)selector, flags); + } + /// + /// Updates a document with the data in doc as found by the selector. + /// + /// The to update with + /// The query spec to find the document to update. + /// + public void Update(object document, object selector, UpdateFlags flags) + { + var descriptor = _serializationFactory.GetBsonDescriptor(typeof(T), _connection); + + var updateMessage = new UpdateMessage(descriptor) + { + FullCollectionName = FullName, + Selector = selector, + Document = document, + Flags = (int)flags + }; + + try + { + _connection.SendMessage(updateMessage); + } + catch(IOException exception) + { + throw new MongoCommException("Could not update document, communication failure", _connection, exception); + } + } + + /// + /// Runs a multiple update query against the database. It will wrap any + /// doc with $set if the passed in doc doesn't contain any '$' ops. + /// + /// The document. + /// The selector. + public void UpdateAll(Document document, Document selector) + { + UpdateAll((object)document, (object)selector); + } + + /// + /// Runs a multiple update query against the database. It will wrap any + /// doc with $set if the passed in doc doesn't contain any '$' ops. + /// + /// The document. + /// The selector. + public void UpdateAll(object document, object selector) + { + var foundOp = false; + + var descriptor = _serializationFactory.GetObjectDescriptor(typeof(T)); + + foreach(var name in descriptor.GetMongoPropertyNames()) + if(name.IndexOf('$') == 0){ + foundOp = true; + break; + } + + if(foundOp == false) + { + //wrap document in a $set. + document = new Document().Add("$set", document); + } + + Update(document, selector, UpdateFlags.MultiUpdate); + } + + /// + /// Updates all. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + public void UpdateAll(Document document, Document selector, bool safemode) + { + UpdateAll((object)document, (object)selector,safemode); + } + /// + /// Updates all. + /// + /// The document. + /// The selector. + /// if set to true [safemode]. + public void UpdateAll(object document, object selector, bool safemode) + { + if(safemode) + Database.ResetError(); + UpdateAll(document, selector); + CheckPreviousError(safemode); + } + + /// + /// Saves a document to the database using an upsert. + /// + /// The document. + /// + /// The document will contain the _id that is saved to the database. This is really just an alias + /// to Update(Document) to maintain consistency between drivers. + /// + public void Save(Document document) + { + Save((object)document); + } + /// + /// Saves a document to the database using an upsert. + /// + /// The document. + /// + /// The document will contain the _id that is saved to the database. This is really just an alias + /// to Update(Document) to maintain consistency between drivers. + /// + public void Save(object document) + { + Update(document); + } + + /// + /// Checks the error. + /// + /// if set to true [safemode]. + private void CheckError(bool safemode){ + if(!safemode) + return; + + var lastError = Database.GetLastError(); + + if(ErrorTranslator.IsError(lastError)) + throw ErrorTranslator.Translate(lastError); + } + + /// + /// Checks the previous error. + /// + /// if set to true [safemode]. + private void CheckPreviousError(bool safemode){ + if(!safemode) + return; + + var previousError = Database.GetPreviousError(); + + if(ErrorTranslator.IsError(previousError)) + throw ErrorTranslator.Translate(previousError); + } + } +} \ No newline at end of file diff --git a/MongoDBDriver/ICursor.cs b/MongoDBDriver/ICursor.cs index fb36f3ad..3f0e5f08 100644 --- a/MongoDBDriver/ICursor.cs +++ b/MongoDBDriver/ICursor.cs @@ -2,24 +2,19 @@ using System.Collections.Generic; namespace MongoDB.Driver { - public interface ICursor : IDisposable + public interface ICursor : IDisposable { - ICursor Spec(Document spec); - ICursor Spec(object spec); - ICursor Limit(int limit); - ICursor Skip(int skip); - ICursor Fields(Document fields); - ICursor Fields(object fields); - ICursor Sort(string field); - ICursor Sort(string field, IndexOrder order); - ICursor Sort(Document fields); - ICursor Sort(object fields); - ICursor Hint(Document index); - ICursor Hint(object index); - ICursor Snapshot(Document index); - ICursor Snapshot(object index); - T Explain(); + ICursor Spec(Document spec); + ICursor Limit(int limit); + ICursor Skip(int skip); + ICursor Fields(Document fields); + ICursor Sort(string field); + ICursor Sort(string field, IndexOrder order); + ICursor Sort(Document fields); + ICursor Hint(Document index); + ICursor Snapshot(); + Document Explain(); bool IsModifiable { get; } - IEnumerable Documents { get; } + IEnumerable Documents { get; } } } diff --git a/MongoDBDriver/IMongoCollection.cs b/MongoDBDriver/IMongoCollection.cs index 77e2ae58..07a067c3 100644 --- a/MongoDBDriver/IMongoCollection.cs +++ b/MongoDBDriver/IMongoCollection.cs @@ -3,36 +3,38 @@ namespace MongoDB.Driver { - public interface IMongoCollection where T : class + /// + /// A collection is a storage unit for a group of s. The documents do not all have to + /// contain the same schema but for efficiency they should all be similar. + /// + /// Safemode checks the database for any errors that may have occurred during + /// the insert such as a duplicate key constraint violation. + public interface IMongoCollection { /// - /// Gets the database. + /// Reference to the this collection is in. /// /// The database. - MongoDatabase Database { get; } + IMongoDatabase Database { get; } /// - /// Gets or sets the name. + /// Name of the collection. /// - /// The name. string Name { get; } /// - /// Gets or sets the name of the database. + /// String value of the database name. /// - /// The name of the database. string DatabaseName { get; } /// - /// Gets the full name including database name. + /// Full name of the collection databasename . collectionname /// - /// The full name. string FullName { get; } /// - /// Gets the meta data. + /// Metadata about the collection such as indexes. /// - /// The meta data. CollectionMetaData MetaData { get; } /// @@ -42,81 +44,53 @@ public interface IMongoCollection where T : class /// /// A from the collection. /// - T FindOne(Document spec); + Document FindOne(Document spec); - /// - /// Finds and returns the first document in a query. - /// - /// A representing the query. - /// - /// A from the collection. - /// - T FindOne(object spec); - - /// - /// Finds all. - /// - /// - ICursor FindAll(); /// - /// Finds the specified where. + /// Returns a cursor that contains all of the documents in the collection. /// - /// The where. - /// - ICursor Find(String where); + /// Cursors load documents from the database in batches instead of all at once. + ICursor FindAll(); /// - /// Finds the specified spec. + /// Uses the $where operator to query the collection. The value of the where is Javascript that will + /// produce a true for the documents that match the criteria. /// - /// The spec. - /// - ICursor Find(Document spec); + /// Javascript + ICursor Find(String where); /// - /// Finds the specified spec. + /// Queries the collection using the specification. /// /// The spec. - /// - ICursor Find(object spec); + /// + /// A + /// + ICursor Find(Document spec); - /// - /// Finds the specified spec. - /// - /// The spec. - /// The limit. - /// The skip. - /// - ICursor Find(Document spec, int limit, int skip); /// - /// Finds the specified spec. + /// Queries the collection using the specification and only returns a subset of fields + /// from the . /// - /// The spec. - /// The limit. - /// The skip. - /// - ICursor Find(object spec, int limit, int skip); - + /// + /// A + /// + ICursor Find(Document spec, Document fields); + + /// - /// Finds the specified spec. + /// Deprecated. Use the fluent interface on the cursor to specify a limit and skip value. /// - /// The spec. - /// The limit. - /// The skip. - /// The fields. - /// - ICursor Find(Document spec, int limit, int skip, Document fields); + [Obsolete("Use the fluent interface on ICursor for specifying limit and skip Find.Skip(x).Limit(y)")] + ICursor Find(Document spec, int limit, int skip); /// - /// Finds the specified spec. + /// Queries the collection using the specification and only returns a subset of fields /// - /// The spec. - /// The limit. - /// The skip. - /// The fields. - /// - ICursor Find(object spec, int limit, int skip, object fields); + [Obsolete("Use the fluent interface on ICursor for specifying limit and skip Find.Skip(x).Limit(y)")] + ICursor Find(Document spec, int limit, int skip, Document fields); /// /// Entrypoint into executing a map/reduce query against the collection. @@ -125,7 +99,7 @@ public interface IMongoCollection where T : class MapReduce MapReduce(); /// - /// Maps the reduce builder. + /// Provides a fluent interface into building a map reduce command against the database. /// /// MapReduceBuilder MapReduceBuilder(); @@ -139,31 +113,17 @@ public interface IMongoCollection where T : class /// Count all items in a collection that match the query spec. /// /// The spec. - /// /// /// It will return 0 if the collection doesn't exist yet. /// long Count(Document spec); - /// - /// Count all items in a collection that match the query spec. - /// - /// The spec. - /// - /// - /// It will return 0 if the collection doesn't exist yet. - /// - long Count(object spec); - /// /// Inserts the Document into the collection. /// + /// See the safemode description in the class description void Insert(Document document, bool safemode); - /// - /// Inserts the Document into the collection. - /// - void Insert(object document, bool safemode); /// /// Inserts the specified doc. @@ -171,58 +131,30 @@ public interface IMongoCollection where T : class /// The doc. void Insert(Document document); - /// - /// Inserts the specified doc. - /// - /// The doc. - void Insert(object document); /// - /// Inserts the specified documents. + /// Bulk inserts the specified documents into the database. /// - /// The documents. - /// if set to true [safemode]. + /// See the safemode description in the class description void Insert(IEnumerable documents, bool safemode); /// - /// Inserts the specified documents. - /// - /// The documents. - /// if set to true [safemode]. - void Insert(IEnumerable documents, bool safemode); - - /// - /// Inserts the specified documents. + /// Bulk inserts the specified documents into the database. /// /// The documents. void Insert(IEnumerable documents); - /// - /// Inserts the specified documents. - /// - /// The documents. - void Insert(IEnumerable documents); /// - /// Deletes documents from the collection according to the spec. + /// Deletes documents from the collection according to the spec. /// /// The selector. - /// if set to true [safemode]. /// - /// An empty document will match all documents in the collection and effectively truncate it. + /// An empty document will match all documents in the collection and effectively truncate it. + /// See the safemode description in the class description /// void Delete(Document selector, bool safemode); - /// - /// Deletes documents from the collection according to the spec. - /// - /// The selector. - /// if set to true [safemode]. - /// - /// An empty document will match all documents in the collection and effectively truncate it. - /// - void Delete(object selector, bool safemode); - /// /// Deletes documents from the collection according to the spec. /// @@ -232,118 +164,63 @@ public interface IMongoCollection where T : class /// void Delete(Document selector); - /// - /// Deletes documents from the collection according to the spec. - /// - /// The selector. - /// - /// An empty document will match all documents in the collection and effectively truncate it. - /// - void Delete(object selector); /// - /// Updates the specified document. + /// Inserts or updates a document in the database. If the document does not contain an _id one will be + /// generated and an upsert sent. Otherwise the document matching the _id of the document will be updated. /// /// The document. - /// if set to true [safemode]. + /// See the safemode description in the class description + [Obsolete("Use Save")] void Update(Document document, bool safemode); /// - /// Updates the specified document. - /// - /// The document. - /// if set to true [safemode]. - void Update(object document, bool safemode); - - /// - /// Updates a document with the data in doc as found by the selector. + /// Inserts or updates a document in the database. If the document does not contain an _id one will be + /// generated and an upsert sent. Otherwise the document matching the _id of the document will be updated. /// /// The document. - /// - /// _id will be used in the document to create a selector. If it isn't in - /// the document then it is assumed that the document is new and an upsert is sent to the database - /// instead. - /// void Update(Document document); /// - /// Updates a document with the data in doc as found by the selector. - /// - /// The document. - /// - /// _id will be used in the document to create a selector. If it isn't in - /// the document then it is assumed that the document is new and an upsert is sent to the database - /// instead. - /// - void Update(object document); - - /// - /// Updates the specified document. + /// Updates the specified document with the current document. In order to only do a partial update use a + /// document containing modifier operations ($set, $unset, $inc, etc.) /// /// The document. /// The selector. - /// if set to true [safemode]. + /// See the safemode description in the class description void Update(Document document, Document selector, bool safemode); /// - /// Updates the specified document. - /// - /// The document. - /// The selector. - /// if set to true [safemode]. - void Update(object document, object selector, bool safemode); - - /// - /// Updates a document with the data in doc as found by the selector. + /// Updates the specified document with the current document. In order to only do a partial update use a + /// document containing modifier operations ($set, $unset, $inc, etc.) /// /// The document. /// The selector. void Update(Document document, Document selector); /// - /// Updates a document with the data in doc as found by the selector. - /// - /// The document. - /// The selector. - void Update(object document, object selector); - - /// - /// Updates the specified document. + /// Updates the specified document with the current document. In order to only do a partial update use a + /// document containing modifier operations ($set, $unset, $inc, etc.) /// /// The document. /// The selector. /// The flags. - /// if set to true [safemode]. + /// See the safemode description in the class description void Update(Document document, Document selector, UpdateFlags flags, bool safemode); - /// - /// Updates the specified document. - /// - /// The document. - /// The selector. - /// The flags. - /// if set to true [safemode]. - void Update(object document, object selector, UpdateFlags flags, bool safemode); /// - /// Updates a document with the data in doc as found by the selector. + /// Updates the specified document with the current document. In order to only do a partial update use a + /// document containing modifier operations ($set, $unset, $inc, etc.) /// /// The to update with /// The query spec to find the document to update. /// void Update(Document document, Document selector, UpdateFlags flags); - /// - /// Updates a document with the data in doc as found by the selector. - /// - /// The to update with - /// The query spec to find the document to update. - /// - void Update(object document, object selector, UpdateFlags flags); - /// /// Runs a multiple update query against the database. It will wrap any - /// doc with $set if the passed in doc doesn't contain any '$' ops. + /// doc with $set if the passed in doc doesn't contain any '$' modifier ops. /// /// The document. /// The selector. @@ -351,30 +228,16 @@ public interface IMongoCollection where T : class /// /// Runs a multiple update query against the database. It will wrap any - /// doc with $set if the passed in doc doesn't contain any '$' ops. - /// - /// The document. - /// The selector. - void UpdateAll(object document, object selector); - - /// - /// Updates all. + /// doc with $set if the passed in doc doesn't contain any '$' modifier ops. /// /// The document. /// The selector. - /// if set to true [safemode]. + /// See the safemode description in the class description void UpdateAll(Document document, Document selector, bool safemode); /// - /// Updates all. - /// - /// The document. - /// The selector. - /// if set to true [safemode]. - void UpdateAll(object document, object selector, bool safemode); - - /// - /// Saves a document to the database using an upsert. + /// Inserts or updates a document in the database. If the document does not contain an _id one will be + /// generated and an upsert sent. Otherwise the document matching the _id of the document will be updated. /// /// The document. /// @@ -383,14 +246,5 @@ public interface IMongoCollection where T : class /// void Save(Document document); - /// - /// Saves a document to the database using an upsert. - /// - /// The document. - /// - /// The document will contain the _id that is saved to the database. This is really just an alias - /// to Update(Document) to maintain consistency between drivers. - /// - void Save(object document); } } \ No newline at end of file diff --git a/MongoDBDriver/IMongoDatabase.cs b/MongoDBDriver/IMongoDatabase.cs index 354c8a9b..8b70a116 100644 --- a/MongoDBDriver/IMongoDatabase.cs +++ b/MongoDBDriver/IMongoDatabase.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using MongoDB.Driver.Generic; + namespace MongoDB.Driver { public interface IMongoDatabase @@ -27,7 +29,7 @@ public interface IMongoDatabase /// Gets the with the specified name. /// /// - IMongoCollection this[String name] { get; } + IMongoCollection this[String name] { get; } /// /// Gets the collection names. @@ -40,7 +42,7 @@ public interface IMongoDatabase /// /// The name. /// - IMongoCollection GetCollection(String name); + IMongoCollection GetCollection(String name); /// /// Gets the collection. diff --git a/MongoDBDriver/MapReduce.cs b/MongoDBDriver/MapReduce.cs index de523f68..a54fd55b 100644 --- a/MongoDBDriver/MapReduce.cs +++ b/MongoDBDriver/MapReduce.cs @@ -9,11 +9,11 @@ namespace MongoDB.Driver public class MapReduce : IDisposable { private readonly Document command; - private readonly MongoDatabase database; + private readonly IMongoDatabase database; private bool canModify = true; private bool disposing; - internal MapReduce(MongoDatabase database, string name){ + internal MapReduce(IMongoDatabase database, string name){ this.database = database; command = new Document().Add("mapreduce", name); Verbose = true; diff --git a/MongoDBDriver/MongoCollection.cs b/MongoDBDriver/MongoCollection.cs index b890dcbe..4019f1f6 100644 --- a/MongoDBDriver/MongoCollection.cs +++ b/MongoDBDriver/MongoCollection.cs @@ -8,10 +8,9 @@ namespace MongoDB.Driver { /// - /// + /// /// - public class MongoCollection : IMongoCollection - where T : class + public class MongoCollection : IMongoCollection { private readonly Connection _connection; private MongoDatabase _database; @@ -35,7 +34,7 @@ public class MongoCollection : IMongoCollection /// Gets the database. /// /// The database. - public MongoDatabase Database{ + public IMongoDatabase Database{ get { return _database ?? (_database = new MongoDatabase(_connection, DatabaseName)); } } @@ -74,19 +73,7 @@ public class MongoCollection : IMongoCollection /// /// A from the collection. /// - public T FindOne(Document spec) - { - return FindOne((object)spec); - } - - /// - /// Finds and returns the first document in a query. - /// - /// A representing the query. - /// - /// A from the collection. - /// - public T FindOne(object spec) + public Document FindOne(Document spec) { var cursor = Find(spec, -1, 0, null); foreach(var document in cursor.Documents) @@ -102,7 +89,7 @@ public T FindOne(object spec) /// Finds all. /// /// - public ICursor FindAll() + public ICursor FindAll() { var spec = new Document(); return Find(spec, 0, 0, null); @@ -113,7 +100,7 @@ public ICursor FindAll() /// /// The where. /// - public ICursor Find(String where) + public ICursor Find(String where) { var spec = new Document{{"$where", new Code(where)}}; return Find(spec, 0, 0, null); @@ -124,33 +111,22 @@ public ICursor Find(String where) /// /// The spec. /// - public ICursor Find(Document spec) - { - return Find((object)spec); - } - - /// - /// Finds the specified spec. - /// - /// The spec. - /// - public ICursor Find(object spec) + public ICursor Find(Document spec) { return Find(spec, 0, 0, null); } /// - /// Finds the specified spec. + /// Finds all Documents in the collection matching spec and only returning the fields requested. /// /// The spec. - /// The limit. - /// The skip. /// - public ICursor Find(Document spec, int limit, int skip) + public ICursor Find(Document spec, Document fields) { - return Find((object)spec, limit, skip, null); + return Find(spec, 0, 0, fields); } - + + /// /// Finds the specified spec. /// @@ -158,7 +134,7 @@ public ICursor Find(Document spec, int limit, int skip) /// The limit. /// The skip. /// - public ICursor Find(object spec, int limit, int skip) + public ICursor Find(Document spec, int limit, int skip) { return Find(spec, limit, skip, null); } @@ -171,24 +147,11 @@ public ICursor Find(object spec, int limit, int skip) /// The skip. /// The fields. /// - public ICursor Find(Document spec, int limit, int skip, Document fields) - { - return Find((object)spec, limit, skip, (object)fields); - } - - /// - /// Finds the specified spec. - /// - /// The spec. - /// The limit. - /// The skip. - /// The fields. - /// - public ICursor Find(object spec, int limit, int skip, object fields) + public ICursor Find(Document spec, int limit, int skip, Document fields) { if(spec == null) spec = new Document(); - return new Cursor(_connection, FullName, spec, limit, skip, fields); + return new Cursor(_connection, FullName, spec, limit, skip, fields); } /// @@ -325,14 +288,14 @@ public void Insert(IEnumerable documents) }; var insertDocument = new List(); - var descriotor = _serializationFactory.GetObjectDescriptor(typeof(T)); + var descriptor = _serializationFactory.GetObjectDescriptor(typeof(Document)); foreach(var document in documents) { - var id = descriotor.GetPropertyValue(document, "_id"); + var id = descriptor.GetPropertyValue(document, "_id"); if(id == null) - descriotor.SetPropertyValue(document, "_id", Oid.NewOid()); + descriptor.SetPropertyValue(document, "_id", Oid.NewOid()); insertDocument.Add(document); } @@ -395,7 +358,7 @@ public void Delete(object selector, bool safemode) /// public void Delete(object selector) { - var descriptor = _serializationFactory.GetBsonDescriptor(typeof(T),_connection); + var descriptor = _serializationFactory.GetBsonDescriptor(typeof(Document),_connection); var deleteMessage = new DeleteMessage(descriptor) { @@ -463,7 +426,7 @@ public void Update(object document) var selector = new Document(); var upsert = UpdateFlags.Upsert; - var descriptor = _serializationFactory.GetObjectDescriptor(typeof(T)); + var descriptor = _serializationFactory.GetObjectDescriptor(typeof(Document)); var value = descriptor.GetPropertyValue(document, "_id"); @@ -563,7 +526,7 @@ public void Update(Document document, Document selector, UpdateFlags flags) /// public void Update(object document, object selector, UpdateFlags flags) { - var descriptor = _serializationFactory.GetBsonDescriptor(typeof(T), _connection); + var descriptor = _serializationFactory.GetBsonDescriptor(typeof(Document), _connection); var updateMessage = new UpdateMessage(descriptor) { @@ -604,7 +567,7 @@ public void UpdateAll(object document, object selector) { var foundOp = false; - var descriptor = _serializationFactory.GetObjectDescriptor(typeof(T)); + var descriptor = _serializationFactory.GetObjectDescriptor(typeof(Document)); foreach(var name in descriptor.GetMongoPropertyNames()) if(name.IndexOf('$') == 0){ diff --git a/MongoDBDriver/MongoDB.Driver.csproj b/MongoDBDriver/MongoDB.Driver.csproj index 61697e1f..befe6569 100644 --- a/MongoDBDriver/MongoDB.Driver.csproj +++ b/MongoDBDriver/MongoDB.Driver.csproj @@ -1,4 +1,4 @@ - + Debug @@ -50,11 +50,12 @@ none - false + true bin\Release prompt 4 false + true False @@ -166,6 +167,10 @@ + + + + @@ -190,4 +195,7 @@ + + + \ No newline at end of file diff --git a/MongoDBDriver/MongoDatabase.cs b/MongoDBDriver/MongoDatabase.cs index 65199821..67d89903 100644 --- a/MongoDBDriver/MongoDatabase.cs +++ b/MongoDBDriver/MongoDatabase.cs @@ -2,8 +2,10 @@ using System.Collections.Generic; using System.Security.Cryptography; using System.Text; + using MongoDB.Driver.CommandResults; using MongoDB.Driver.Connections; +using MongoDB.Driver.Generic; namespace MongoDB.Driver { @@ -62,7 +64,7 @@ public MongoDatabase(string connectionString, String name) /// Gets the with the specified name. /// /// - public IMongoCollection this[String name]{ + public IMongoCollection this[String name]{ get { return GetCollection(name); } } @@ -84,8 +86,8 @@ public MongoDatabase(string connectionString, String name) /// /// The name. /// - public IMongoCollection GetCollection(String name){ - return new MongoCollection(_connection, Name, name); + public IMongoCollection GetCollection(String name){ + return new MongoCollection(_connection, Name, name); } /// diff --git a/examples/Simple/Main.cs b/examples/Simple/Main.cs index 0d4bb563..7e637102 100644 --- a/examples/Simple/Main.cs +++ b/examples/Simple/Main.cs @@ -17,7 +17,7 @@ class MainClass { Mongo mongo; MongoDatabase simple; - IMongoCollection categories; + IMongoCollection categories; public static void Main (string[] args){ MainClass main = new MainClass(); @@ -76,7 +76,7 @@ class MainClass //Find(new Document()) is equivalent to FindAll(); //Specifying the cursor in a using block will close it on the server if we decide not //to iterate through the whole thing. - using(ICursor all = categories.Find(new Document())) + using(ICursor all = categories.Find(new Document())) { foreach(Document doc in all.Documents){ Console.WriteLine(doc.ToString()); diff --git a/examples/SimpleVB/Application.vb b/examples/SimpleVB/Application.vb index 61d23c32..2c378f55 100644 --- a/examples/SimpleVB/Application.vb +++ b/examples/SimpleVB/Application.vb @@ -16,7 +16,7 @@ Namespace Simple Public Class Application Private mongo as Mongo Private simple as IMongoDatabase - Private categories as IMongoCollection(Of Document) + Private categories as IMongoCollection Public Shared Sub Main() Dim app As New Application() @@ -76,7 +76,7 @@ Namespace Simple 'Find(new Document()) is equivalent to FindAll() 'Specifying the cursor in a using block will close it on the server if we decide not 'to iterate through the whole thing. - Dim all As ICursor(Of Document) = categories.Find(New Document()) + Dim all As ICursor = categories.Find(New Document()) Try For Each doc As Document In all.Documents Console.WriteLine(doc.ToString())