Skip to content

Commit

Permalink
Merge remote branch 'craig/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
lanwin committed Jul 14, 2010
2 parents 893fba8 + ab62f7e commit 828ea90
Show file tree
Hide file tree
Showing 22 changed files with 148 additions and 89 deletions.
Expand Up @@ -123,7 +123,7 @@ public void Enum()
Assert.AreEqual(0, queryObject.Fields.Count);
Assert.AreEqual(0, queryObject.NumberToLimit);
Assert.AreEqual(0, queryObject.NumberToSkip);
Assert.AreEqual(new Document("PrimaryAddress.AddressType", AddressType.Company), queryObject.Query);
Assert.AreEqual(new Document("PrimaryAddress.AddressType", (int)AddressType.Company), queryObject.Query);
}

[Test]
Expand Down
8 changes: 8 additions & 0 deletions source/MongoDB.Tests/IntegrationTests/Linq/MongoQueryTests.cs
Expand Up @@ -63,6 +63,14 @@ public override void TestSetup()
true);
}

[Test]
public void Any()
{
var anyone = Collection.Linq().Any(x => x.Age <= 21);

Assert.IsTrue(anyone);
}

[Test]
public void Boolean()
{
Expand Down
3 changes: 3 additions & 0 deletions source/MongoDB/Attributes/MongoAliasAttribute.cs
Expand Up @@ -21,6 +21,9 @@ public sealed class MongoAliasAttribute : Attribute
public MongoAliasAttribute(string name){
if(name == null)
throw new ArgumentNullException("name");
if (name == "_id")
throw new ArgumentException("_id is a reserved alias.");

Name = name;
}
}
Expand Down
19 changes: 18 additions & 1 deletion source/MongoDB/Attributes/MongoDefaultAttribute.cs
Expand Up @@ -8,14 +8,31 @@ namespace MongoDB.Attributes
[AttributeUsage(AttributeTargets.Property)]
public sealed class MongoDefaultAttribute : Attribute
{

/// <summary>
/// Initializes a new instance of the <see cref="MongoDefaultAttribute"/> class.
/// </summary>
/// <param name="value">The value.</param>
public MongoDefaultAttribute(object value){
public MongoDefaultAttribute(object value)
: this(value, true)
{ }

/// <summary>
/// Initializes a new instance of the <see cref="MongoDefaultAttribute"/> class.
/// </summary>
/// <param name="value">The value.</param>
public MongoDefaultAttribute(object value, bool persistDefaultValue)
{
Value = value;
PersistDefaultValue = persistDefaultValue;
}

/// <summary>
/// Gets or sets a value indicating whether the default value should be persisted.
/// </summary>
/// <value><c>true</c> if [persist default value]; otherwise, <c>false</c>.</value>
public bool PersistDefaultValue { get; private set; }

/// <summary>
/// Gets or sets the value.
/// </summary>
Expand Down
17 changes: 17 additions & 0 deletions source/MongoDB/Attributes/MongoIdAttribute.cs
@@ -0,0 +1,17 @@
using System;

namespace MongoDB.Attributes
{
/// <summary>
///
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class MongoIdAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="MongoIdAttribute"/> class.
/// </summary>
public MongoIdAttribute()
{ }
}
}
Expand Up @@ -55,12 +55,12 @@ public MemberOverridesBuilder Ignore()
}

/// <summary>
/// Persists the null.
/// Persists the default value.
/// </summary>
/// <returns></returns>
public MemberOverridesBuilder PersistNull()
public MemberOverridesBuilder PersistDefaultValue()
{
_overrides.PersistIfNull = true;
_overrides.PersistDefaultValue = true;
return this;
}
}
Expand Down
6 changes: 3 additions & 3 deletions source/MongoDB/Configuration/Mapping/Auto/AutoMapper.cs
Expand Up @@ -183,7 +183,7 @@ public AutoMapper(Func<Type, bool> filter)
MemberReflectionOptimizer.GetGetter(member),
MemberReflectionOptimizer.GetSetter(member),
_profile.GetAlias(classType, member),
_profile.GetPersistNull(classType, member),
_profile.GetPersistDefaultValue(classType, member),
dictionaryAdapter);

var collectionType = _profile.GetCollectionAdapter(classType, member, memberReturnType);
Expand All @@ -194,7 +194,7 @@ public AutoMapper(Func<Type, bool> filter)
MemberReflectionOptimizer.GetGetter(member),
MemberReflectionOptimizer.GetSetter(member),
_profile.GetAlias(classType, member),
_profile.GetPersistNull(classType, member),
_profile.GetPersistDefaultValue(classType, member),
collectionType,
_profile.GetCollectionElementType(classType, member, memberReturnType));

Expand All @@ -207,7 +207,7 @@ public AutoMapper(Func<Type, bool> filter)
MemberReflectionOptimizer.GetSetter(member),
_profile.GetDefaultValue(classType, member),
_profile.GetAlias(classType, member),
_profile.GetPersistNull(classType, member));
_profile.GetPersistDefaultValue(classType, member));
}
}
}
19 changes: 16 additions & 3 deletions source/MongoDB/Configuration/Mapping/Auto/AutoMappingProfile.cs
Expand Up @@ -95,7 +95,16 @@ public MemberInfo FindExtendedPropertiesMember(Type classType)
/// <returns></returns>
public MemberInfo FindIdMember(Type classType)
{
return _conventions.IdConvention.GetIdMember(classType);
var members = (from memberInfo in _memberFinder.FindMembers(classType)
let att = memberInfo.GetCustomAttribute<MongoIdAttribute>(true)
where att != null
select memberInfo).ToList();

if (members.Count > 1)
throw new InvalidOperationException("Cannot have more than 1 member marked with a MongoId Attribute.");
if(members.Count == 0)
return _conventions.IdConvention.GetIdMember(classType);
return members[0];
}

/// <summary>
Expand Down Expand Up @@ -238,9 +247,13 @@ public object GetIdUnsavedValue(Type classType, MemberInfo member)
/// <param name="classType">Type of the class.</param>
/// <param name="member">The member.</param>
/// <returns></returns>
public bool GetPersistNull(Type classType, MemberInfo member)
public bool GetPersistDefaultValue(Type classType, MemberInfo member)
{
return false;
var att = member.GetCustomAttribute<MongoDefaultAttribute>(true);
if (att != null)
return att.PersistDefaultValue;

return true;
}

/// <summary>
Expand Down
Expand Up @@ -115,12 +115,12 @@ public interface IAutoMappingProfile
object GetIdUnsavedValue(Type classType, MemberInfo member);

/// <summary>
/// Gets a value indicating whether the member should be persisted if it is null.
/// Gets a value indicating whether the member should be persisted if it is it's default value.
/// </summary>
/// <param name="classType">Type of the class.</param>
/// <param name="member">The member.</param>
/// <returns></returns>
bool GetPersistNull(Type classType, MemberInfo member);
bool GetPersistDefaultValue(Type classType, MemberInfo member);

/// <summary>
/// Indicates whether the class type is a sub class.
Expand Down
6 changes: 3 additions & 3 deletions source/MongoDB/Configuration/Mapping/Auto/MemberOverrides.cs
Expand Up @@ -23,9 +23,9 @@ public class MemberOverrides
public bool? Ignore { get; set; }

/// <summary>
/// Gets or sets a value indicating whether.
/// Gets or sets a value indicating whether a member with the default value gets persisted.
/// </summary>
/// <value><c>true</c> if [persist if null]; otherwise, <c>false</c>.</value>
public bool? PersistIfNull { get; set; }
/// <value>The persist default value.</value>
public bool? PersistDefaultValue { get; set; }
}
}
Expand Up @@ -205,13 +205,13 @@ public object GetIdUnsavedValue(Type classType, MemberInfo member)
/// <param name = "classType">Type of the class.</param>
/// <param name = "member">The member.</param>
/// <returns></returns>
public bool GetPersistNull(Type classType, MemberInfo member)
public bool GetPersistDefaultValue(Type classType, MemberInfo member)
{
return (bool)GetMemberOverrideValue(classType,
member,
o => o.PersistIfNull,
o => o.PersistDefaultValue,
v => v.HasValue,
_profile.GetPersistNull(classType, member));
_profile.GetPersistDefaultValue(classType, member));
}

/// <summary>
Expand Down
Expand Up @@ -26,11 +26,11 @@ public class CollectionMemberMap : PersistentMemberMap
/// <param name="getter">The getter.</param>
/// <param name="setter">The setter.</param>
/// <param name="alias">The alias.</param>
/// <param name="persistNull">if set to <c>true</c> [persist null].</param>
/// <param name="persistDefaultValue">if set to <c>true</c> [persist default value].</param>
/// <param name="collectionAdapter">Type of the collection.</param>
/// <param name="elementType">Type of the element.</param>
public CollectionMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, string alias, bool persistNull, ICollectionAdapter collectionAdapter, Type elementType)
: base(memberName, memberReturnType, getter, setter, null, alias, persistNull)
public CollectionMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, string alias, bool persistDefaultValue, ICollectionAdapter collectionAdapter, Type elementType)
: base(memberName, memberReturnType, getter, setter, null, alias, persistDefaultValue)
{
_collectionAdapter = collectionAdapter;
ElementType = elementType;
Expand Down
Expand Up @@ -36,10 +36,10 @@ public Type ValueType
/// <param name="getter">The getter.</param>
/// <param name="setter">The setter.</param>
/// <param name="alias">The alias.</param>
/// <param name="persistNull">if set to <c>true</c> [persist null].</param>
/// <param name="persistDefaultValue">if set to <c>true</c> [persist default value].</param>
/// <param name="dictionaryAdapter">The dictionary adapter.</param>
public DictionaryMemberMap(string memberName, Func<object, object> getter, Action<object, object> setter, string alias, bool persistNull, IDictionaryAdapter dictionaryAdapter)
: base(memberName, typeof(Document), getter, setter, null, alias, persistNull)
public DictionaryMemberMap(string memberName, Func<object, object> getter, Action<object, object> setter, string alias, bool persistDefaultValue, IDictionaryAdapter dictionaryAdapter)
: base(memberName, typeof(Document), getter, setter, null, alias, persistDefaultValue)
{
_dictionaryAdapter = dictionaryAdapter;
}
Expand Down
Expand Up @@ -20,12 +20,10 @@ public class PersistentMemberMap : MemberMapBase
public object DefaultValue { get; private set; }

/// <summary>
/// Gets a value indicating whether or not null should be persisted to the database.
/// Gets or sets a value indicating whether the default value should be persisted.
/// </summary>
/// <value>
/// <c>true</c> if the null should be persisted; otherwise, <c>false</c>.
/// </value>
public bool PersistNull { get; private set; }
/// <value><c>true</c> if the default value should be persisted; otherwise, <c>false</c>.</value>
public bool PersistDefaultValue { get; private set; }

/// <summary>
/// Initializes a new instance of the <see cref="PersistentMemberMap"/> class.
Expand All @@ -36,13 +34,13 @@ public class PersistentMemberMap : MemberMapBase
/// <param name="setter">The setter.</param>
/// <param name="defaultValue">The default value.</param>
/// <param name="alias">The alias.</param>
/// <param name="persistNull">if set to <c>true</c> [persist null].</param>
public PersistentMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, object defaultValue, string alias, bool persistNull)
/// <param name="persistDefaultValue">if set to <c>true</c> [persist default value].</param>
public PersistentMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, object defaultValue, string alias, bool persistDefaultValue)
: base(memberName, memberReturnType, getter, setter)
{
Alias = alias;
DefaultValue = defaultValue;
PersistNull = persistNull;
PersistDefaultValue = persistDefaultValue;
}
}
}
4 changes: 2 additions & 2 deletions source/MongoDB/Linq/MongoQueryProvider.cs
Expand Up @@ -160,7 +160,7 @@ private Expression BuildExecutionPlan(Expression expression)
return new ExecutionBuilder().Build(projection, provider);
}

private ProjectionExpression Translate(Expression expression)
private Expression Translate(Expression expression)
{
var rootQueryable = new RootQueryableFinder().Find(expression);
var elementType = ((IQueryable)((ConstantExpression)rootQueryable).Value).ElementType;
Expand All @@ -177,7 +177,7 @@ private ProjectionExpression Translate(Expression expression)
expression = new RedundantFieldRemover().Remove(expression);
expression = new RedundantSubqueryRemover().Remove(expression);

return (ProjectionExpression)expression;
return expression;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion source/MongoDB/Linq/Translators/MongoQueryObjectBuilder.cs
Expand Up @@ -9,7 +9,7 @@ internal class MongoQueryObjectBuilder : MongoExpressionVisitor
private MongoQueryObject _queryObject;
private QueryAttributes _queryAttributes;

internal MongoQueryObject Build(ProjectionExpression expression)
internal MongoQueryObject Build(Expression expression)
{
_queryObject = new MongoQueryObject();
_queryAttributes = new QueryAttributesGatherer().Gather(expression);
Expand Down
22 changes: 22 additions & 0 deletions source/MongoDB/Linq/Translators/QueryBinder.cs
Expand Up @@ -128,6 +128,11 @@ protected override Expression VisitMethodCall(MethodCallExpression m)
{
switch (m.Method.Name)
{
case "Any":
if (m.Arguments.Count == 1)
return BindAny(m.Arguments[0], null, m == _root);
else
return BindAny(m.Arguments[0], (LambdaExpression)StripQuotes(m.Arguments[1]), m == _root);
case "Where":
return BindWhere(m.Type, m.Arguments[0], (LambdaExpression)StripQuotes(m.Arguments[1]));
case "Select":
Expand Down Expand Up @@ -273,6 +278,23 @@ private Expression BindAggregate(Expression source, MethodInfo method, LambdaExp
return subquery;
}

private Expression BindAny(Expression source, LambdaExpression predicate, bool isRoot)
{
var projection = VisitSequence(source);
var sourceType = projection.Projector.Type;

MethodInfo method = typeof(Queryable)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(m => m.Name == "Count")
.Single(m => m.GetParameters().Length == (predicate == null ? 1 : 2))
.GetGenericMethodDefinition().MakeGenericMethod(sourceType);

var expression = BindAggregate(source, method, predicate, isRoot);

return Expression.GreaterThan(
expression, Expression.Constant(0));
}

private Expression BindDistinct(Expression source)
{
var projection = VisitSequence(source);
Expand Down
1 change: 1 addition & 0 deletions source/MongoDB/MongoDB.csproj
Expand Up @@ -102,6 +102,7 @@
<Compile Include="..\..\AssemblyInfoGlobal.cs">
<Link>AssemblyInfoGlobal.cs</Link>
</Compile>
<Compile Include="Attributes\MongoIdAttribute.cs" />
<Compile Include="BinarySubtype.cs" />
<Compile Include="Bson\BsonType.cs" />
<Compile Include="Bson\BsonInfo.cs" />
Expand Down
Expand Up @@ -41,7 +41,12 @@ public override IEnumerable<BsonProperty> GetProperties()
yield return CreateProperty(ClassMap.DiscriminatorAlias, ClassMap.Discriminator.GetType(), ClassMap.Discriminator, false);

foreach (var memberMap in ClassMap.MemberMaps)
yield return CreateProperty(memberMap.Alias, GetValue(memberMap.MemberName));
{
var value = GetValue(memberMap.MemberName);
if (!memberMap.PersistDefaultValue && object.Equals(memberMap.DefaultValue, value))
continue;
yield return CreateProperty(memberMap.Alias, value);
}

if (_extendedProperties == null)
yield break;
Expand All @@ -62,7 +67,7 @@ private BsonPropertyValue GetValue(string name)

object value;

var memberMap = GetMemberMapFromMemberName(name);
var memberMap = GetAliasFromMemberName(name).MemberMap;
if(memberMap != null)
value = memberMap.GetValue(_instance);
else if (_extendedProperties != null)
Expand Down

0 comments on commit 828ea90

Please sign in to comment.