Skip to content

Commit 828ea90

Browse files
committed
Merge remote branch 'craig/master'
2 parents 893fba8 + ab62f7e commit 828ea90

22 files changed

+148
-89
lines changed

source/MongoDB.Tests/IntegrationTests/Linq/MongoQueryProviderTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public void Enum()
123123
Assert.AreEqual(0, queryObject.Fields.Count);
124124
Assert.AreEqual(0, queryObject.NumberToLimit);
125125
Assert.AreEqual(0, queryObject.NumberToSkip);
126-
Assert.AreEqual(new Document("PrimaryAddress.AddressType", AddressType.Company), queryObject.Query);
126+
Assert.AreEqual(new Document("PrimaryAddress.AddressType", (int)AddressType.Company), queryObject.Query);
127127
}
128128

129129
[Test]

source/MongoDB.Tests/IntegrationTests/Linq/MongoQueryTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ public override void TestSetup()
6363
true);
6464
}
6565

66+
[Test]
67+
public void Any()
68+
{
69+
var anyone = Collection.Linq().Any(x => x.Age <= 21);
70+
71+
Assert.IsTrue(anyone);
72+
}
73+
6674
[Test]
6775
public void Boolean()
6876
{

source/MongoDB/Attributes/MongoAliasAttribute.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ public sealed class MongoAliasAttribute : Attribute
2121
public MongoAliasAttribute(string name){
2222
if(name == null)
2323
throw new ArgumentNullException("name");
24+
if (name == "_id")
25+
throw new ArgumentException("_id is a reserved alias.");
26+
2427
Name = name;
2528
}
2629
}

source/MongoDB/Attributes/MongoDefaultAttribute.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,31 @@ namespace MongoDB.Attributes
88
[AttributeUsage(AttributeTargets.Property)]
99
public sealed class MongoDefaultAttribute : Attribute
1010
{
11+
1112
/// <summary>
1213
/// Initializes a new instance of the <see cref="MongoDefaultAttribute"/> class.
1314
/// </summary>
1415
/// <param name="value">The value.</param>
15-
public MongoDefaultAttribute(object value){
16+
public MongoDefaultAttribute(object value)
17+
: this(value, true)
18+
{ }
19+
20+
/// <summary>
21+
/// Initializes a new instance of the <see cref="MongoDefaultAttribute"/> class.
22+
/// </summary>
23+
/// <param name="value">The value.</param>
24+
public MongoDefaultAttribute(object value, bool persistDefaultValue)
25+
{
1626
Value = value;
27+
PersistDefaultValue = persistDefaultValue;
1728
}
1829

30+
/// <summary>
31+
/// Gets or sets a value indicating whether the default value should be persisted.
32+
/// </summary>
33+
/// <value><c>true</c> if [persist default value]; otherwise, <c>false</c>.</value>
34+
public bool PersistDefaultValue { get; private set; }
35+
1936
/// <summary>
2037
/// Gets or sets the value.
2138
/// </summary>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace MongoDB.Attributes
4+
{
5+
/// <summary>
6+
///
7+
/// </summary>
8+
[AttributeUsage(AttributeTargets.Property)]
9+
public sealed class MongoIdAttribute : Attribute
10+
{
11+
/// <summary>
12+
/// Initializes a new instance of the <see cref="MongoIdAttribute"/> class.
13+
/// </summary>
14+
public MongoIdAttribute()
15+
{ }
16+
}
17+
}

source/MongoDB/Configuration/Builders/MemberOverridesBuilder.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ public MemberOverridesBuilder Ignore()
5555
}
5656

5757
/// <summary>
58-
/// Persists the null.
58+
/// Persists the default value.
5959
/// </summary>
6060
/// <returns></returns>
61-
public MemberOverridesBuilder PersistNull()
61+
public MemberOverridesBuilder PersistDefaultValue()
6262
{
63-
_overrides.PersistIfNull = true;
63+
_overrides.PersistDefaultValue = true;
6464
return this;
6565
}
6666
}

source/MongoDB/Configuration/Mapping/Auto/AutoMapper.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ private PersistentMemberMap CreateMemberMap(Type classType, MemberInfo member){
183183
MemberReflectionOptimizer.GetGetter(member),
184184
MemberReflectionOptimizer.GetSetter(member),
185185
_profile.GetAlias(classType, member),
186-
_profile.GetPersistNull(classType, member),
186+
_profile.GetPersistDefaultValue(classType, member),
187187
dictionaryAdapter);
188188

189189
var collectionType = _profile.GetCollectionAdapter(classType, member, memberReturnType);
@@ -194,7 +194,7 @@ private PersistentMemberMap CreateMemberMap(Type classType, MemberInfo member){
194194
MemberReflectionOptimizer.GetGetter(member),
195195
MemberReflectionOptimizer.GetSetter(member),
196196
_profile.GetAlias(classType, member),
197-
_profile.GetPersistNull(classType, member),
197+
_profile.GetPersistDefaultValue(classType, member),
198198
collectionType,
199199
_profile.GetCollectionElementType(classType, member, memberReturnType));
200200

@@ -207,7 +207,7 @@ private PersistentMemberMap CreateMemberMap(Type classType, MemberInfo member){
207207
MemberReflectionOptimizer.GetSetter(member),
208208
_profile.GetDefaultValue(classType, member),
209209
_profile.GetAlias(classType, member),
210-
_profile.GetPersistNull(classType, member));
210+
_profile.GetPersistDefaultValue(classType, member));
211211
}
212212
}
213213
}

source/MongoDB/Configuration/Mapping/Auto/AutoMappingProfile.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,16 @@ public MemberInfo FindExtendedPropertiesMember(Type classType)
9595
/// <returns></returns>
9696
public MemberInfo FindIdMember(Type classType)
9797
{
98-
return _conventions.IdConvention.GetIdMember(classType);
98+
var members = (from memberInfo in _memberFinder.FindMembers(classType)
99+
let att = memberInfo.GetCustomAttribute<MongoIdAttribute>(true)
100+
where att != null
101+
select memberInfo).ToList();
102+
103+
if (members.Count > 1)
104+
throw new InvalidOperationException("Cannot have more than 1 member marked with a MongoId Attribute.");
105+
if(members.Count == 0)
106+
return _conventions.IdConvention.GetIdMember(classType);
107+
return members[0];
99108
}
100109

101110
/// <summary>
@@ -238,9 +247,13 @@ public object GetIdUnsavedValue(Type classType, MemberInfo member)
238247
/// <param name="classType">Type of the class.</param>
239248
/// <param name="member">The member.</param>
240249
/// <returns></returns>
241-
public bool GetPersistNull(Type classType, MemberInfo member)
250+
public bool GetPersistDefaultValue(Type classType, MemberInfo member)
242251
{
243-
return false;
252+
var att = member.GetCustomAttribute<MongoDefaultAttribute>(true);
253+
if (att != null)
254+
return att.PersistDefaultValue;
255+
256+
return true;
244257
}
245258

246259
/// <summary>

source/MongoDB/Configuration/Mapping/Auto/IAutoMappingProfile.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,12 @@ public interface IAutoMappingProfile
115115
object GetIdUnsavedValue(Type classType, MemberInfo member);
116116

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

125125
/// <summary>
126126
/// Indicates whether the class type is a sub class.

source/MongoDB/Configuration/Mapping/Auto/MemberOverrides.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ public class MemberOverrides
2323
public bool? Ignore { get; set; }
2424

2525
/// <summary>
26-
/// Gets or sets a value indicating whether.
26+
/// Gets or sets a value indicating whether a member with the default value gets persisted.
2727
/// </summary>
28-
/// <value><c>true</c> if [persist if null]; otherwise, <c>false</c>.</value>
29-
public bool? PersistIfNull { get; set; }
28+
/// <value>The persist default value.</value>
29+
public bool? PersistDefaultValue { get; set; }
3030
}
3131
}

source/MongoDB/Configuration/Mapping/Auto/OverridableAutoMappingProfile.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,13 @@ public object GetIdUnsavedValue(Type classType, MemberInfo member)
205205
/// <param name = "classType">Type of the class.</param>
206206
/// <param name = "member">The member.</param>
207207
/// <returns></returns>
208-
public bool GetPersistNull(Type classType, MemberInfo member)
208+
public bool GetPersistDefaultValue(Type classType, MemberInfo member)
209209
{
210210
return (bool)GetMemberOverrideValue(classType,
211211
member,
212-
o => o.PersistIfNull,
212+
o => o.PersistDefaultValue,
213213
v => v.HasValue,
214-
_profile.GetPersistNull(classType, member));
214+
_profile.GetPersistDefaultValue(classType, member));
215215
}
216216

217217
/// <summary>

source/MongoDB/Configuration/Mapping/Model/CollectionMemberMap.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ public class CollectionMemberMap : PersistentMemberMap
2626
/// <param name="getter">The getter.</param>
2727
/// <param name="setter">The setter.</param>
2828
/// <param name="alias">The alias.</param>
29-
/// <param name="persistNull">if set to <c>true</c> [persist null].</param>
29+
/// <param name="persistDefaultValue">if set to <c>true</c> [persist default value].</param>
3030
/// <param name="collectionAdapter">Type of the collection.</param>
3131
/// <param name="elementType">Type of the element.</param>
32-
public CollectionMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, string alias, bool persistNull, ICollectionAdapter collectionAdapter, Type elementType)
33-
: base(memberName, memberReturnType, getter, setter, null, alias, persistNull)
32+
public CollectionMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, string alias, bool persistDefaultValue, ICollectionAdapter collectionAdapter, Type elementType)
33+
: base(memberName, memberReturnType, getter, setter, null, alias, persistDefaultValue)
3434
{
3535
_collectionAdapter = collectionAdapter;
3636
ElementType = elementType;

source/MongoDB/Configuration/Mapping/Model/DictionaryMemberMap.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ public Type ValueType
3636
/// <param name="getter">The getter.</param>
3737
/// <param name="setter">The setter.</param>
3838
/// <param name="alias">The alias.</param>
39-
/// <param name="persistNull">if set to <c>true</c> [persist null].</param>
39+
/// <param name="persistDefaultValue">if set to <c>true</c> [persist default value].</param>
4040
/// <param name="dictionaryAdapter">The dictionary adapter.</param>
41-
public DictionaryMemberMap(string memberName, Func<object, object> getter, Action<object, object> setter, string alias, bool persistNull, IDictionaryAdapter dictionaryAdapter)
42-
: base(memberName, typeof(Document), getter, setter, null, alias, persistNull)
41+
public DictionaryMemberMap(string memberName, Func<object, object> getter, Action<object, object> setter, string alias, bool persistDefaultValue, IDictionaryAdapter dictionaryAdapter)
42+
: base(memberName, typeof(Document), getter, setter, null, alias, persistDefaultValue)
4343
{
4444
_dictionaryAdapter = dictionaryAdapter;
4545
}

source/MongoDB/Configuration/Mapping/Model/PersistentMemberMap.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@ public class PersistentMemberMap : MemberMapBase
2020
public object DefaultValue { get; private set; }
2121

2222
/// <summary>
23-
/// Gets a value indicating whether or not null should be persisted to the database.
23+
/// Gets or sets a value indicating whether the default value should be persisted.
2424
/// </summary>
25-
/// <value>
26-
/// <c>true</c> if the null should be persisted; otherwise, <c>false</c>.
27-
/// </value>
28-
public bool PersistNull { get; private set; }
25+
/// <value><c>true</c> if the default value should be persisted; otherwise, <c>false</c>.</value>
26+
public bool PersistDefaultValue { get; private set; }
2927

3028
/// <summary>
3129
/// Initializes a new instance of the <see cref="PersistentMemberMap"/> class.
@@ -36,13 +34,13 @@ public class PersistentMemberMap : MemberMapBase
3634
/// <param name="setter">The setter.</param>
3735
/// <param name="defaultValue">The default value.</param>
3836
/// <param name="alias">The alias.</param>
39-
/// <param name="persistNull">if set to <c>true</c> [persist null].</param>
40-
public PersistentMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, object defaultValue, string alias, bool persistNull)
37+
/// <param name="persistDefaultValue">if set to <c>true</c> [persist default value].</param>
38+
public PersistentMemberMap(string memberName, Type memberReturnType, Func<object, object> getter, Action<object, object> setter, object defaultValue, string alias, bool persistDefaultValue)
4139
: base(memberName, memberReturnType, getter, setter)
4240
{
4341
Alias = alias;
4442
DefaultValue = defaultValue;
45-
PersistNull = persistNull;
43+
PersistDefaultValue = persistDefaultValue;
4644
}
4745
}
4846
}

source/MongoDB/Linq/MongoQueryProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ private Expression BuildExecutionPlan(Expression expression)
160160
return new ExecutionBuilder().Build(projection, provider);
161161
}
162162

163-
private ProjectionExpression Translate(Expression expression)
163+
private Expression Translate(Expression expression)
164164
{
165165
var rootQueryable = new RootQueryableFinder().Find(expression);
166166
var elementType = ((IQueryable)((ConstantExpression)rootQueryable).Value).ElementType;
@@ -177,7 +177,7 @@ private ProjectionExpression Translate(Expression expression)
177177
expression = new RedundantFieldRemover().Remove(expression);
178178
expression = new RedundantSubqueryRemover().Remove(expression);
179179

180-
return (ProjectionExpression)expression;
180+
return expression;
181181
}
182182

183183
/// <summary>

source/MongoDB/Linq/Translators/MongoQueryObjectBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ internal class MongoQueryObjectBuilder : MongoExpressionVisitor
99
private MongoQueryObject _queryObject;
1010
private QueryAttributes _queryAttributes;
1111

12-
internal MongoQueryObject Build(ProjectionExpression expression)
12+
internal MongoQueryObject Build(Expression expression)
1313
{
1414
_queryObject = new MongoQueryObject();
1515
_queryAttributes = new QueryAttributesGatherer().Gather(expression);

source/MongoDB/Linq/Translators/QueryBinder.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ protected override Expression VisitMethodCall(MethodCallExpression m)
128128
{
129129
switch (m.Method.Name)
130130
{
131+
case "Any":
132+
if (m.Arguments.Count == 1)
133+
return BindAny(m.Arguments[0], null, m == _root);
134+
else
135+
return BindAny(m.Arguments[0], (LambdaExpression)StripQuotes(m.Arguments[1]), m == _root);
131136
case "Where":
132137
return BindWhere(m.Type, m.Arguments[0], (LambdaExpression)StripQuotes(m.Arguments[1]));
133138
case "Select":
@@ -273,6 +278,23 @@ private Expression BindAggregate(Expression source, MethodInfo method, LambdaExp
273278
return subquery;
274279
}
275280

281+
private Expression BindAny(Expression source, LambdaExpression predicate, bool isRoot)
282+
{
283+
var projection = VisitSequence(source);
284+
var sourceType = projection.Projector.Type;
285+
286+
MethodInfo method = typeof(Queryable)
287+
.GetMethods(BindingFlags.Public | BindingFlags.Static)
288+
.Where(m => m.Name == "Count")
289+
.Single(m => m.GetParameters().Length == (predicate == null ? 1 : 2))
290+
.GetGenericMethodDefinition().MakeGenericMethod(sourceType);
291+
292+
var expression = BindAggregate(source, method, predicate, isRoot);
293+
294+
return Expression.GreaterThan(
295+
expression, Expression.Constant(0));
296+
}
297+
276298
private Expression BindDistinct(Expression source)
277299
{
278300
var projection = VisitSequence(source);

source/MongoDB/MongoDB.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
<Compile Include="..\..\AssemblyInfoGlobal.cs">
103103
<Link>AssemblyInfoGlobal.cs</Link>
104104
</Compile>
105+
<Compile Include="Attributes\MongoIdAttribute.cs" />
105106
<Compile Include="BinarySubtype.cs" />
106107
<Compile Include="Bson\BsonType.cs" />
107108
<Compile Include="Bson\BsonInfo.cs" />

source/MongoDB/Serialization/Descriptors/ClassMapPropertyDescriptor.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ public override IEnumerable<BsonProperty> GetProperties()
4141
yield return CreateProperty(ClassMap.DiscriminatorAlias, ClassMap.Discriminator.GetType(), ClassMap.Discriminator, false);
4242

4343
foreach (var memberMap in ClassMap.MemberMaps)
44-
yield return CreateProperty(memberMap.Alias, GetValue(memberMap.MemberName));
44+
{
45+
var value = GetValue(memberMap.MemberName);
46+
if (!memberMap.PersistDefaultValue && object.Equals(memberMap.DefaultValue, value))
47+
continue;
48+
yield return CreateProperty(memberMap.Alias, value);
49+
}
4550

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

6368
object value;
6469

65-
var memberMap = GetMemberMapFromMemberName(name);
70+
var memberMap = GetAliasFromMemberName(name).MemberMap;
6671
if(memberMap != null)
6772
value = memberMap.GetValue(_instance);
6873
else if (_extendedProperties != null)

0 commit comments

Comments
 (0)