Skip to content
Browse files

Merge remote branch 'craig/master'

  • Loading branch information...
2 parents 1ee5f56 + 30d8109 commit 059cdc9508d3bae1a8e385ad774d189d4d2456db unknown committed
View
280 source/MongoDB.Tests/IntegrationTests/Inheritance/TestInheritanceWithAbstractBaseClass.cs
@@ -0,0 +1,280 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace MongoDB.IntegrationTests.Inheritance
+{
+ [TestFixture]
+ public class TestInheritanceWithAbstractBaseClass : MongoTestBase
+ {
+ abstract class Animal
+ {
+ public Oid Id { get; set; }
+
+ public int Age { get; set; }
+
+ public string Name { get; set; }
+ }
+
+ class Bear : Animal
+ { }
+
+ abstract class Cat : Animal
+ { }
+
+ class Tiger : Cat
+ { }
+
+ class Lion : Cat
+ { }
+
+ public override string TestCollections
+ {
+ get { return "Animal"; }
+ }
+
+ [SetUp]
+ public void TestSetup()
+ {
+ CleanDB();
+ }
+
+ protected override Configuration.MongoConfigurationBuilder GetConfiguration()
+ {
+ var builder = base.GetConfiguration();
+ builder.Mapping(mapping =>
+ {
+ mapping.DefaultProfile(profile =>
+ {
+ profile.SubClassesAre(x => x.IsSubclassOf(typeof(Animal)));
+ });
+
+ mapping.Map<Bear>();
+ mapping.Map<Cat>();
+ mapping.Map<Tiger>();
+ mapping.Map<Lion>();
+ });
+
+ return builder;
+ }
+
+ [Test]
+ public void Should_persist_discriminator_using_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var docCollection = DB.GetCollection<Document>("Animal");
+
+ var docs = docCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(new[] { "Cat", "Tiger" }, (List<string>)docs[0]["_t"]);
+ Assert.AreEqual("Bear", (string)docs[1]["_t"]);
+ }
+
+ [Test]
+ public void Should_persist_discriminator_using_concrete_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Cat>();
+ animalCollection.Save(new Lion() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var docCollection = DB.GetCollection<Document>("Animal");
+
+ var docs = docCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(new[] { "Cat", "Tiger" }, (List<string>)docs[0]["_t"]);
+ Assert.AreEqual(new[] { "Cat", "Lion" }, (List<string>)docs[1]["_t"]);
+ }
+
+ [Test]
+ public void Should_fetch_with_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var animals = animalCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.AreEqual("Bob", animals[0].Name);
+ Assert.IsInstanceOfType(typeof(Bear), animals[1]);
+ Assert.AreEqual(20, animals[1].Age);
+ Assert.AreEqual("Jim", animals[1].Name);
+ }
+
+ [Test]
+ public void Should_fetch_with_base_class_collection_through_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var animals = (from a in animalCollection.Linq()
+ orderby a.Age ascending
+ select a).ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.AreEqual("Bob", animals[0].Name);
+ Assert.IsInstanceOfType(typeof(Bear), animals[1]);
+ Assert.AreEqual(20, animals[1].Age);
+ Assert.AreEqual("Jim", animals[1].Name);
+ }
+
+ [Test]
+ public void Should_support_projections_with_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var animals = animalCollection.FindAll().Fields(new { Age = true }).Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.IsNull(animals[0].Name);
+ Assert.IsInstanceOfType(typeof(Bear), animals[1]);
+ Assert.AreEqual(20, animals[1].Age);
+ Assert.IsNull(animals[1].Name);
+ }
+
+ [Test]
+ public void Should_support_projections_with_base_class_collections_with_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var animals = (from a in animalCollection.Linq()
+ orderby a.Age ascending
+ select new { a.Name, a.Age }).ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.AreEqual("Bob", animals[0].Name);
+ Assert.AreEqual(20, animals[1].Age);
+ Assert.AreEqual("Jim", animals[1].Name);
+ }
+
+ [Test]
+ public void Should_support_projections_with_concrete_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var cats = catCollection.FindAll().Fields(new { Age = true }).Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(1, cats.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), cats[0]);
+ Assert.AreEqual(19, cats[0].Age);
+ Assert.IsNull(cats[0].Name);
+ }
+
+ [Test]
+ public void Should_support_projections_with_concrete_class_collections_with_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var cats = (from a in catCollection.Linq()
+ orderby a.Age ascending
+ select new { a.Name, a.Age }).ToList();
+
+ Assert.AreEqual(1, cats.Count);
+ Assert.AreEqual(19, cats[0].Age);
+ Assert.AreEqual("Bob", cats[0].Name);
+ }
+
+ [Test]
+ public void Should_fetch_with_concrete_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var cats = catCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(1, cats.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), cats[0]);
+ Assert.AreEqual(19, cats[0].Age);
+ }
+
+ [Test]
+ public void Should_fetch_with_concrete_class_collection_through_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var animals = (from a in catCollection.Linq()
+ orderby a.Age ascending
+ select a).ToList();
+
+ Assert.AreEqual(1, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ Assert.AreEqual(2, animalCollection.Count());
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_base_class_collection_using_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ Assert.AreEqual(2, animalCollection.Linq().Count());
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_concrete_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ Assert.AreEqual(1, catCollection.Count());
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_concrete_class_collection_using_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Bear() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ Assert.AreEqual(1, catCollection.Linq().Count());
+ }
+ }
+}
View
276 source/MongoDB.Tests/IntegrationTests/Inheritance/TestInheritanceWithConcreteBaseClass.cs
@@ -0,0 +1,276 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace MongoDB.IntegrationTests.Inheritance
+{
+ [TestFixture]
+ public class TestInheritanceWithConcreteBaseClass : MongoTestBase
+ {
+ class Animal
+ {
+ public Oid Id { get; set; }
+
+ public int Age { get; set; }
+
+ public string Name { get; set; }
+ }
+
+ class Bear : Animal
+ { }
+
+ abstract class Cat : Animal
+ { }
+
+ class Tiger : Cat
+ { }
+
+ class Lion : Cat
+ { }
+
+ public override string TestCollections
+ {
+ get { return "Animal"; }
+ }
+
+ [SetUp]
+ public void TestSetup()
+ {
+ CleanDB();
+ }
+
+ protected override Configuration.MongoConfigurationBuilder GetConfiguration()
+ {
+ var builder = base.GetConfiguration();
+ builder.Mapping(mapping =>
+ {
+ mapping.DefaultProfile(profile =>
+ {
+ profile.SubClassesAre(x => x.IsSubclassOf(typeof(Animal)));
+ });
+
+ mapping.Map<Bear>();
+ mapping.Map<Cat>();
+ mapping.Map<Tiger>();
+ mapping.Map<Lion>();
+ });
+
+ return builder;
+ }
+
+ [Test]
+ public void Should_persist_discriminator_using_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var docCollection = DB.GetCollection<Document>("Animal");
+
+ var docs = docCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(new[] { "Cat", "Tiger" }, (List<string>)docs[0]["_t"]);
+ Assert.IsNull(docs[1]["_t"]);
+ }
+
+ [Test]
+ public void Should_persist_discriminator_using_inherited_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Cat>();
+ animalCollection.Save(new Lion() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var docCollection = DB.GetCollection<Document>("Animal");
+
+ var docs = docCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(new[] { "Cat", "Tiger" }, (List<string>)docs[0]["_t"]);
+ Assert.AreEqual(new[] { "Cat", "Lion" }, (List<string>)docs[1]["_t"]);
+ }
+
+ [Test]
+ public void Should_fetch_with_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var animals = animalCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.IsInstanceOfType(typeof(Animal), animals[1]);
+ Assert.AreEqual(20, animals[1].Age);
+ }
+
+ [Test]
+ public void Should_fetch_with_base_class_collection_through_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var animals = (from a in animalCollection.Linq()
+ orderby a.Age ascending
+ select a).ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.IsInstanceOfType(typeof(Animal), animals[1]);
+ Assert.AreEqual(20, animals[1].Age);
+ }
+
+ [Test]
+ public void Should_fetch_with_inherited_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var cats = catCollection.FindAll().Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(1, cats.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), cats[0]);
+ Assert.AreEqual(19, cats[0].Age);
+ }
+
+ [Test]
+ public void Should_fetch_with_inherited_class_collection_through_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var animals = (from a in catCollection.Linq()
+ orderby a.Age ascending
+ select a).ToList();
+
+ Assert.AreEqual(1, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ }
+
+ [Test]
+ public void Should_support_projections_with_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var animals = animalCollection.FindAll().Fields(new { Age = true }).Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), animals[0]);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.IsNull(animals[0].Name);
+ Assert.IsInstanceOfType(typeof(Animal), animals[1]);
+ Assert.AreEqual(20, animals[1].Age);
+ Assert.IsNull(animals[1].Name);
+ }
+
+ [Test]
+ public void Should_support_projections_with_base_class_collections_with_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var animals = (from a in animalCollection.Linq()
+ orderby a.Age ascending
+ select new { a.Name, a.Age }).ToList();
+
+ Assert.AreEqual(2, animals.Count);
+ Assert.AreEqual(19, animals[0].Age);
+ Assert.AreEqual("Bob", animals[0].Name);
+ Assert.AreEqual(20, animals[1].Age);
+ Assert.AreEqual("Jim", animals[1].Name);
+ }
+
+ [Test]
+ public void Should_support_projections_with_inherited_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var cats = catCollection.FindAll().Fields(new { Age = true }).Sort("Age", IndexOrder.Ascending).Documents.ToList();
+
+ Assert.AreEqual(1, cats.Count);
+ Assert.IsInstanceOfType(typeof(Tiger), cats[0]);
+ Assert.AreEqual(19, cats[0].Age);
+ Assert.IsNull(cats[0].Name);
+ }
+
+ [Test]
+ public void Should_support_projections_with_inherited_class_collections_with_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20, Name = "Jim" });
+ animalCollection.Save(new Tiger() { Age = 19, Name = "Bob" });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ var cats = (from a in catCollection.Linq()
+ orderby a.Age ascending
+ select new { a.Name, a.Age }).ToList();
+
+ Assert.AreEqual(1, cats.Count);
+ Assert.AreEqual(19, cats[0].Age);
+ Assert.AreEqual("Bob", cats[0].Name);
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_base_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ Assert.AreEqual(2, animalCollection.Count());
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_base_class_collection_using_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ Assert.AreEqual(2, animalCollection.Linq().Count());
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_inherited_class_collection()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ Assert.AreEqual(1, catCollection.Count());
+ }
+
+ [Test]
+ public void Should_get_correct_count_with_inherited_class_collection_using_linq()
+ {
+ var animalCollection = DB.GetCollection<Animal>();
+ animalCollection.Save(new Animal() { Age = 20 });
+ animalCollection.Save(new Tiger() { Age = 19 });
+
+ var catCollection = DB.GetCollection<Cat>();
+
+ Assert.AreEqual(1, catCollection.Linq().Count());
+ }
+ }
+}
View
3 source/MongoDB.Tests/IntegrationTests/TestDatabase.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
+using System.Configuration;
namespace MongoDB.IntegrationTests
{
@@ -126,7 +127,7 @@ public class TestDatabase : MongoTestBase
[Test]
public void TestCanCreateFromConnectionString(){
- var builder = new MongoConnectionStringBuilder(ConnectionString) {Database = "tests"};
+ var builder = new MongoConnectionStringBuilder(ConfigurationManager.AppSettings["tests"]) {Database = "tests"};
/*
using(var database = new MongoDatabase(builder.ToString()))
{
View
2 source/MongoDB.Tests/MongoDB.Tests.csproj
@@ -89,6 +89,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="IntegrationTests\Inheritance\TestInheritanceWithConcreteBaseClass.cs" />
+ <Compile Include="IntegrationTests\Inheritance\TestInheritanceWithAbstractBaseClass.cs" />
<Compile Include="IntegrationTests\SecondServer\TestPooledConnectionFactory.cs" />
<Compile Include="IntegrationTests\Linq\LinqDomain.cs" />
<Compile Include="IntegrationTests\Linq\MapReduceTests.cs" />
View
19 source/MongoDB.Tests/MongoTestBase.cs
@@ -1,6 +1,7 @@
using System;
using System.Configuration;
using NUnit.Framework;
+using MongoDB.Configuration;
namespace MongoDB
{
@@ -15,12 +16,6 @@ public abstract class MongoTestBase
}
/// <summary>
- /// Gets or sets the connection string.
- /// </summary>
- /// <value>The connection string.</value>
- public string ConnectionString { get; private set; }
-
- /// <summary>
/// Comma separated list of collections to clean at startup.
/// </summary>
public abstract string TestCollections{get;}
@@ -40,10 +35,7 @@ public abstract class MongoTestBase
/// </summary>
[TestFixtureSetUp]
public virtual void Init(){
- ConnectionString = ConfigurationManager.AppSettings["tests"];
- if(String.IsNullOrEmpty(ConnectionString))
- throw new ArgumentNullException("Connection string not found.");
- this.Mongo = new Mongo(ConnectionString);
+ this.Mongo = new Mongo(GetConfiguration().BuildConfiguration());
this.Mongo.Connect();
CleanDB();
OnInit();
@@ -62,5 +54,12 @@ public abstract class MongoTestBase
//Console.WriteLine("Dropping " + col);
}
}
+
+ protected virtual MongoConfigurationBuilder GetConfiguration()
+ {
+ var builder = new MongoConfigurationBuilder();
+ builder.ReadConnectionStringFromAppSettings("tests");
+ return builder;
+ }
}
}
View
3 source/MongoDB/Configuration/Mapping/Model/ClassMapBase.cs
@@ -145,6 +145,9 @@ public object CreateInstance()
if(!_hasProtectedOrPublicConstructor)
throw new MissingMethodException("No public or protected constructor found on type " + ClassType.FullName);
+ if (ClassType.IsAbstract)
+ throw new MongoException("Unable to create an instance of an abstract class.");
+
//TODO: figure out how to support custom activators...
var instance = Activator.CreateInstance(ClassType, true);
View
4 source/MongoDB/Connections/Connection.cs
@@ -8,7 +8,7 @@
using MongoDB.Serialization;
using MongoDB.Util;
-namespace MongoDB.Connections
+namespace MongoDB.Connections
{
/// <summary>
/// Connection is a managment unit which uses a RawConnection from connection pool
@@ -18,7 +18,7 @@ namespace MongoDB.Connections
/// by a new fresh connection.
/// </remarks>
/// </summary>
- internal class Connection : IDisposable
+ internal class Connection : IDisposable
{
private readonly IConnectionFactory _factory;
private RawConnection _connection;
View
434 source/MongoDB/Cursor_1.cs
@@ -1,30 +1,34 @@
-using System;
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.IO;
-using MongoDB.Connections;
-using MongoDB.Protocol;
+using MongoDB.Connections;
+using MongoDB.Protocol;
using MongoDB.Serialization;
using System.Linq;
+using MongoDB.Util;
+using MongoDB.Configuration.Mapping.Model;
+using MongoDB.Configuration.Mapping;
-namespace MongoDB
+namespace MongoDB
{
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
- public class Cursor<T> : ICursor<T> where T : class
+ public class Cursor<T> : ICursor<T> where T : class
{
private readonly Connection _connection;
private readonly string _databaseName;
private readonly Document _specOpts = new Document();
- private object _spec;
- private object _fields;
- private int _limit;
- private QueryOptions _options;
- private ReplyMessage<T> _reply;
+ private object _spec;
+ private object _fields;
+ private int _limit;
+ private QueryOptions _options;
+ private ReplyMessage<T> _reply;
private int _skip;
private bool _keepCursor;
private readonly ISerializationFactory _serializationFactory;
+ private readonly IMappingStore _mappingStore;
/// <summary>
/// Initializes a new instance of the <see cref="Cursor&lt;T&gt;"/> class.
@@ -33,14 +37,15 @@ public class Cursor<T> : ICursor<T> where T : class
/// <param name="connection">The conn.</param>
/// <param name="databaseName">Name of the database.</param>
/// <param name="collectionName">Name of the collection.</param>
- internal Cursor(ISerializationFactory serializationFactory, Connection connection, string databaseName, string collectionName)
+ internal Cursor(ISerializationFactory serializationFactory, IMappingStore mappingStore, Connection connection, string databaseName, string collectionName)
{
//Todo: add public constrcutor for users to call
IsModifiable = true;
_connection = connection;
_databaseName = databaseName;
FullCollectionName = databaseName + "." + collectionName;
- _serializationFactory = serializationFactory;
+ _serializationFactory = serializationFactory;
+ _mappingStore = mappingStore;
}
/// <summary>
@@ -54,16 +59,16 @@ internal Cursor(ISerializationFactory serializationFactory, Connection connectio
/// <param name="limit">The limit.</param>
/// <param name="skip">The skip.</param>
/// <param name="fields">The fields.</param>
- internal Cursor(ISerializationFactory serializationFactory, Connection connection, string databaseName, string collectionName, object spec, int limit, int skip, object fields)
- : this(serializationFactory, connection, databaseName, collectionName)
+ internal Cursor(ISerializationFactory serializationFactory, IMappingStore mappingStore, Connection connection, string databaseName, string collectionName, object spec, int limit, int skip, object fields)
+ : this(serializationFactory, mappingStore, connection, databaseName, collectionName)
{
- //Todo: add public constrcutor for users to call
- if (spec == null)
- spec = new Document();
- _spec = spec;
- _limit = limit;
- _skip = skip;
- _fields = fields;
+ //Todo: add public constrcutor for users to call
+ if (spec == null)
+ spec = new Document();
+ _spec = spec;
+ _limit = limit;
+ _skip = skip;
+ _fields = fields;
}
/// <summary>
@@ -72,103 +77,103 @@ internal Cursor(ISerializationFactory serializationFactory, Connection connectio
/// </summary>
~Cursor(){
Dispose(false);
- }
-
- /// <summary>
- /// Gets or sets the full name of the collection.
- /// </summary>
- /// <value>The full name of the collection.</value>
- public string FullCollectionName { get; private set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
+ }
+
+ /// <summary>
+ /// Gets or sets the full name of the collection.
+ /// </summary>
+ /// <value>The full name of the collection.</value>
+ public string FullCollectionName { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
public long Id { get; private set; }
- /// <summary>
- /// Specs the specified spec.
- /// </summary>
- /// <param name="spec">The spec.</param>
- /// <returns></returns>
- public ICursor<T> Spec(object spec){
- TryModify();
- _spec = spec;
- return this;
- }
-
- /// <summary>
- /// Limits the specified limit.
- /// </summary>
- /// <param name="limit">The limit.</param>
- /// <returns></returns>
- public ICursor<T> Limit(int limit){
- TryModify();
- _limit = limit;
- return this;
- }
-
- /// <summary>
- /// Skips the specified skip.
- /// </summary>
- /// <param name="skip">The skip.</param>
- /// <returns></returns>
- public ICursor<T> Skip(int skip){
- TryModify();
- _skip = skip;
- return this;
+ /// <summary>
+ /// Specs the specified spec.
+ /// </summary>
+ /// <param name="spec">The spec.</param>
+ /// <returns></returns>
+ public ICursor<T> Spec(object spec){
+ TryModify();
+ _spec = spec;
+ return this;
}
- /// <summary>
- /// Fieldses the specified fields.
- /// </summary>
- /// <param name="fields">The fields.</param>
- /// <returns></returns>
- public ICursor<T> Fields(object fields){
- TryModify();
- _fields = fields;
- return this;
- }
-
- /// <summary>
- /// Sorts the specified field.
- /// </summary>
- /// <param name = "field">The field.</param>
- /// <returns></returns>
- public ICursor<T> Sort(string field){
- return Sort(field, IndexOrder.Ascending);
- }
-
- /// <summary>
- /// Sorts the specified field.
- /// </summary>
- /// <param name = "field">The field.</param>
- /// <param name = "order">The order.</param>
- /// <returns></returns>
- public ICursor<T> Sort(string field, IndexOrder order){
- return Sort(new Document().Add(field, order));
+ /// <summary>
+ /// Limits the specified limit.
+ /// </summary>
+ /// <param name="limit">The limit.</param>
+ /// <returns></returns>
+ public ICursor<T> Limit(int limit){
+ TryModify();
+ _limit = limit;
+ return this;
}
- /// <summary>
- /// Sorts the specified fields.
- /// </summary>
- /// <param name="fields">The fields.</param>
- /// <returns></returns>
- public ICursor<T> Sort(object fields){
- TryModify();
- AddOrRemoveSpecOpt("$orderby", fields);
- return this;
+ /// <summary>
+ /// Skips the specified skip.
+ /// </summary>
+ /// <param name="skip">The skip.</param>
+ /// <returns></returns>
+ public ICursor<T> Skip(int skip){
+ TryModify();
+ _skip = skip;
+ return this;
}
- /// <summary>
- /// Hints the specified index.
- /// </summary>
- /// <param name="index">The index.</param>
- /// <returns></returns>
- public ICursor<T> Hint(object index){
- TryModify();
- AddOrRemoveSpecOpt("$hint", index);
- return this;
+ /// <summary>
+ /// Fieldses the specified fields.
+ /// </summary>
+ /// <param name="fields">The fields.</param>
+ /// <returns></returns>
+ public ICursor<T> Fields(object fields){
+ TryModify();
+ _fields = fields;
+ return this;
+ }
+
+ /// <summary>
+ /// Sorts the specified field.
+ /// </summary>
+ /// <param name = "field">The field.</param>
+ /// <returns></returns>
+ public ICursor<T> Sort(string field){
+ return Sort(field, IndexOrder.Ascending);
+ }
+
+ /// <summary>
+ /// Sorts the specified field.
+ /// </summary>
+ /// <param name = "field">The field.</param>
+ /// <param name = "order">The order.</param>
+ /// <returns></returns>
+ public ICursor<T> Sort(string field, IndexOrder order){
+ return Sort(new Document().Add(field, order));
+ }
+
+ /// <summary>
+ /// Sorts the specified fields.
+ /// </summary>
+ /// <param name="fields">The fields.</param>
+ /// <returns></returns>
+ public ICursor<T> Sort(object fields){
+ TryModify();
+ AddOrRemoveSpecOpt("$orderby", fields);
+ return this;
+ }
+
+ /// <summary>
+ /// Hints the specified index.
+ /// </summary>
+ /// <param name="index">The index.</param>
+ /// <returns></returns>
+ public ICursor<T> Hint(object index){
+ TryModify();
+ AddOrRemoveSpecOpt("$hint", index);
+ return this;
}
/// <summary>
@@ -185,31 +190,31 @@ public ICursor<T> KeepCursor(bool value)
_keepCursor = value;
return this;
}
-
- /// <summary>
- /// Snapshots the specified index.
- /// </summary>
- public ICursor<T> Snapshot(){
- TryModify();
- AddOrRemoveSpecOpt("$snapshot", true);
- return this;
+
+ /// <summary>
+ /// Snapshots the specified index.
+ /// </summary>
+ public ICursor<T> Snapshot(){
+ TryModify();
+ AddOrRemoveSpecOpt("$snapshot", true);
+ return this;
}
-
- /// <summary>
- /// Explains this instance.
- /// </summary>
- /// <returns></returns>
- public Document Explain(){
- TryModify();
+
+ /// <summary>
+ /// Explains this instance.
+ /// </summary>
+ /// <returns></returns>
+ public Document Explain(){
+ TryModify();
_specOpts["$explain"] = true;
- var explainResult = RetrieveData<Document>();
+ var explainResult = RetrieveData<Document>();
try
{
var explain = explainResult.Documents.FirstOrDefault();
if(explain==null)
- throw new InvalidOperationException("Explain failed. No documents where returned.");
+ throw new InvalidOperationException("Explain failed. No documents where returned.");
return explain;
}
@@ -217,20 +222,20 @@ public ICursor<T> KeepCursor(bool value)
{
if(explainResult.CursorId > 0)
KillCursor(explainResult.CursorId);
- }
+ }
}
- /// <summary>
- /// Gets a value indicating whether this <see cref = "Cursor&lt;T&gt;" /> is modifiable.
- /// </summary>
+ /// <summary>
+ /// Gets a value indicating whether this <see cref = "Cursor&lt;T&gt;" /> is modifiable.
+ /// </summary>
/// <value><c>true</c> if modifiable; otherwise, <c>false</c>.</value>
public bool IsModifiable { get; private set; }
- /// <summary>
- /// Gets the documents.
- /// </summary>
- /// <value>The documents.</value>
- public IEnumerable<T> Documents {
+ /// <summary>
+ /// Gets the documents.
+ /// </summary>
+ /// <value>The documents.</value>
+ public IEnumerable<T> Documents {
get {
do
{
@@ -246,7 +251,7 @@ public ICursor<T> KeepCursor(bool value)
if(!_keepCursor)
Dispose(true);
- }
+ }
}
/// <summary>
@@ -264,9 +269,9 @@ public int CursorPosition
}
}
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
public void Dispose()
{
Dispose(true);
@@ -285,15 +290,15 @@ protected virtual void Dispose(bool disposing)
KillCursor(Id);
}
- /// <summary>
- /// Optionses the specified options.
- /// </summary>
- /// <param name = "options">The options.</param>
- /// <returns></returns>
- public ICursor<T> Options(QueryOptions options){
- TryModify();
- _options = options;
- return this;
+ /// <summary>
+ /// Optionses the specified options.
+ /// </summary>
+ /// <param name = "options">The options.</param>
+ /// <returns></returns>
+ public ICursor<T> Options(QueryOptions options){
+ TryModify();
+ _options = options;
+ return this;
}
/// <summary>
@@ -301,13 +306,13 @@ protected virtual void Dispose(bool disposing)
/// </summary>
private void KillCursor(long cursorId)
{
- var killCursorsMessage = new KillCursorsMessage(cursorId);
-
- try {
+ var killCursorsMessage = new KillCursorsMessage(cursorId);
+
+ try {
_connection.SendMessage(killCursorsMessage,_databaseName);
- Id = 0;
- } catch (IOException exception) {
- throw new MongoConnectionException("Could not read data, communication failure", _connection, exception);
+ Id = 0;
+ } catch (IOException exception) {
+ throw new MongoConnectionException("Could not read data, communication failure", _connection, exception);
}
}
@@ -333,7 +338,7 @@ private void KillCursor(long cursorId)
NumberToReturn = _limit,
NumberToSkip = _skip,
Options = _options,
- ReturnFieldSelector = _fields
+ ReturnFieldSelector = ConvertFieldSelectorToDocument(_fields)
};
}
else
@@ -357,39 +362,86 @@ private void KillCursor(long cursorId)
throw new MongoConnectionException("Could not read data, communication failure", _connection, exception);
}
}
-
- /// <summary>
- /// Tries the modify.
- /// </summary>
+
+ /// <summary>
+ /// Tries the modify.
+ /// </summary>
private void TryModify(){
if(!IsModifiable)
- throw new InvalidOperationException("Cannot modify a cursor that has already returned documents.");
- }
-
- /// <summary>
- /// Adds the or remove spec opt.
- /// </summary>
- /// <param name = "key">The key.</param>
- /// <param name = "doc">The doc.</param>
- private void AddOrRemoveSpecOpt(string key, object doc){
- if (doc == null)
- _specOpts.Remove(key);
- else
- _specOpts[key] = doc;
- }
-
- /// <summary>
- /// Builds the spec.
- /// </summary>
- /// <returns></returns>
- private object BuildSpec(){
- if (_specOpts.Count == 0)
- return _spec;
-
- var document = new Document();
- _specOpts.CopyTo(document);
- document["$query"] = _spec;
- return document;
- }
- }
-}
+ throw new InvalidOperationException("Cannot modify a cursor that has already returned documents.");
+ }
+
+ /// <summary>
+ /// Adds the or remove spec opt.
+ /// </summary>
+ /// <param name = "key">The key.</param>
+ /// <param name = "doc">The doc.</param>
+ private void AddOrRemoveSpecOpt(string key, object doc){
+ if (doc == null)
+ _specOpts.Remove(key);
+ else
+ _specOpts[key] = doc;
+ }
+
+ /// <summary>
+ /// Builds the spec.
+ /// </summary>
+ /// <returns></returns>
+ private object BuildSpec(){
+ if (_specOpts.Count == 0)
+ return _spec;
+
+ var document = new Document();
+ _specOpts.CopyTo(document);
+ document["$query"] = _spec;
+ return document;
+ }
+
+ private Document ConvertFieldSelectorToDocument(object document)
+ {
+ Document doc;
+ if (document == null)
+ doc = new Document();
+ else
+ doc = ConvertExampleToDocument(document) as Document;
+
+ if (doc == null)
+ throw new NotSupportedException("An entity type is not supported in field selection. Use either a document or an anonymous type.");
+
+ var classMap = _mappingStore.GetClassMap(typeof(T));
+ if (doc.Count > 0 && (classMap.IsPolymorphic || classMap.IsSubClass))
+ doc[classMap.DiscriminatorAlias] = true;
+
+ return doc.Count == 0 ? null : doc;
+ }
+
+ private object ConvertExampleToDocument(object document)
+ {
+ if (document == null)
+ return null;
+
+ Document doc = document as Document;
+ if (doc != null)
+ return doc;
+
+ doc = new Document();
+
+ if (!(document is T)) //some type that is being used as an example
+ {
+ foreach (var prop in document.GetType().GetProperties())
+ {
+ if (!prop.CanRead)
+ continue;
+
+ object value = prop.GetValue(document, null);
+ if (!TypeHelper.IsNativeToMongo(prop.PropertyType))
+ value = ConvertExampleToDocument(value);
+
+ doc[prop.Name] = value;
+ }
+ }
+
+ return doc;
+ }
+ }
+}
View
16 source/MongoDB/MongoCollection_1.cs
@@ -7,6 +7,7 @@
using MongoDB.Protocol;
using MongoDB.Results;
using MongoDB.Util;
+using MongoDB.Configuration.Mapping.Model;
namespace MongoDB
{
@@ -158,7 +159,7 @@ public T FindOne(string javascriptWhere)
public ICursor<T> Find(object spec, int limit, int skip, object fields){
if (spec == null)
spec = new Document();
- return new Cursor<T>(_configuration.SerializationFactory, _connection, DatabaseName, Name, spec, limit, skip, fields);
+ return new Cursor<T>(_configuration.SerializationFactory, _configuration.MappingStore, _connection, DatabaseName, Name, spec, limit, skip, fields);
}
/// <summary>
@@ -211,12 +212,17 @@ public T FindOne(string javascriptWhere)
try
{
var command = new Document
- {
+ {
+ {"findandmodify", Name},
+ {"query", spec},
+ {"update", EnsureUpdateDocument(document)},
+ {"sort", sort},
+ {"new", returnNew}
};
- {"update", EnsureUpdateDocument(document)},
- {"sort", sort},
- {"new", returnNew}
+ var response = _connection.SendCommand<FindAndModifyResult<T>>(_configuration.SerializationFactory,
+ DatabaseName,
+ typeof(T),
command);
return response.Value;
View
2 source/MongoDB/Serialization/Builders/PolymorphicClassMapBuilder.cs
@@ -41,6 +41,8 @@ public object BuildObject()
{
//we'll assume that this is the root class in the hierarchy.
_concreteEntityBuilder = new ConcreteClassMapBuilder(_classMap);
+ foreach (var pair in _properties)
+ _concreteEntityBuilder.AddProperty(pair.Key, pair.Value);
}
return _concreteEntityBuilder.BuildObject();
View
2 source/MongoDB/Serialization/ClassMapObjectDescriptorAdapter.cs
@@ -35,7 +35,7 @@ public IEnumerable<string> GetMongoPropertyNames(object instance)
if (_classMap.HasId)
yield return _classMap.IdMap.Alias;
- if (_classMap.IsPolymorphic && _classMap.HasDiscriminator)
+ if (_classMap.IsSubClass)
yield return _classMap.DiscriminatorAlias;
foreach (var memberMap in _classMap.MemberMaps)
View
4 source/MongoDB/Serialization/Descriptors/ClassMapPropertyDescriptor.cs
@@ -37,7 +37,7 @@ public override IEnumerable<BsonProperty> GetProperties()
if (ClassMap.HasId)
yield return CreateProperty(ClassMap.IdMap.Alias, ClassMap.IdMap.MemberReturnType, ClassMap.GetId(_instance), false);
- if (ShouldPersistDiscriminator())
+ if (ShouldAddDiscriminator())
yield return CreateProperty(ClassMap.DiscriminatorAlias, ClassMap.Discriminator.GetType(), ClassMap.Discriminator, false);
foreach (var memberMap in ClassMap.MemberMaps)
@@ -62,7 +62,7 @@ public override IEnumerable<BsonProperty> GetProperties()
/// <returns></returns>
private BsonPropertyValue GetValue(string name)
{
- if (ClassMap.DiscriminatorAlias == name && ShouldPersistDiscriminator())
+ if (ClassMap.DiscriminatorAlias == name && ShouldAddDiscriminator())
return new BsonPropertyValue(ClassMap.Discriminator.GetType(), ClassMap.Discriminator, false);
object value;
View
4 source/MongoDB/Serialization/Descriptors/ClassMapPropertyDescriptorBase.cs
@@ -71,9 +71,9 @@ protected BsonProperty CreateProperty(string alias, BsonPropertyValue value)
/// Shoulds the persist discriminator.
/// </summary>
/// <returns></returns>
- protected bool ShouldPersistDiscriminator()
+ protected bool ShouldAddDiscriminator()
{
- return (ClassMap.IsPolymorphic && ClassMap.HasDiscriminator) || ClassMap.IsSubClass;
+ return ClassMap.IsSubClass;
}
/// <summary>
View
4 source/MongoDB/Serialization/Descriptors/DocumentClassMapPropertyDescriptor.cs
@@ -31,7 +31,7 @@ public DocumentClassMapPropertyDescriptor(IMappingStore mappingStore, IClassMap
/// <returns></returns>
public override IEnumerable<BsonProperty> GetProperties()
{
- if(ShouldPersistDiscriminator())
+ if(ShouldAddDiscriminator())
{
if (_document.ContainsKey("count")) //this is a special case
{
@@ -65,7 +65,7 @@ public override IEnumerable<BsonProperty> GetProperties()
/// <returns></returns>
private BsonPropertyValue GetValue(string name)
{
- if (ClassMap.DiscriminatorAlias == name && ShouldPersistDiscriminator())
+ if (ClassMap.DiscriminatorAlias == name && ShouldAddDiscriminator())
return new BsonPropertyValue(ClassMap.Discriminator.GetType(), ClassMap.Discriminator, false);
var value = _document[name];
View
2 source/MongoDB/Serialization/Descriptors/ExampleClassMapPropertyDescriptor.cs
@@ -34,7 +34,7 @@ public ExampleClassMapPropertyDescriptor(IMappingStore mappingStore, IClassMap c
/// <returns></returns>
public override IEnumerable<BsonProperty> GetProperties()
{
- if (ShouldPersistDiscriminator())
+ if (ShouldAddDiscriminator())
yield return CreateProperty(ClassMap.DiscriminatorAlias, ClassMap.Discriminator.GetType(), ClassMap.Discriminator, false);
foreach (PropertyInfo propertyInfo in _exampleType.GetProperties())
View
19 source/MongoDB/Util/TypeHelper.cs
@@ -54,5 +54,24 @@ internal static Type GetNonNullableType(Type type)
{
return IsNullableType(type) ? type.GetGenericArguments()[0] : type;
}
+
+ internal static bool IsNativeToMongo(Type type)
+ {
+ var typeCode = Type.GetTypeCode(type);
+
+ if (typeCode != TypeCode.Object)
+ return true;
+
+ if (type == typeof(Guid))
+ return true;
+
+ if (type == typeof(Oid))
+ return true;
+
+ if (type == typeof(byte[]))
+ return true;
+
+ return false;
+ }
}
}

0 comments on commit 059cdc9

Please sign in to comment.
Something went wrong with that request. Please try again.