Reputation: 16056
I know that MongoDb C# driver doesn't support projections so I searched a little bit and I found that many people uses a mongoCursor to perform such queries, I'm trying to select only specific fields and my code is the following:
public T GetSingle<T>(Expression<Func<T, bool>> criteria,params Expression<Func<T, object>>[] fields) where T : class
{
Collection = GetCollection<T>();
return Collection.FindAs<T>(Query<T>.Where(criteria)).SetFields(Fields<T>.Include(fields)).SetLimit(1).SingleOrDefault();
}
I got and custom repository for users on top of that:
public User GetByEmail(string mail, params Expression<Func<User, object>>[] fields)
{
return GetSingle<User>(x=>x.Email==mail,fields);
}
this is the usage:
_repository.GetByEmail(email, x=>x.Id,x=>x.DisplayName,x=>x.ProfilePicture)
but I'm getting the fields included in the parameter but also all the Enums,dates and Boolean values that are part of the class User, the values that are string and not included in the field list are null so that's fine
what can I do to avoid that?
Upvotes: 1
Views: 3682
Reputation: 46301
By using SetFields
, you can specify what goes through the wire. However, you're still asking the driver to return hydrated objects of type T
, User
in this case.
Now, similar to say an int
, enum
and boolean
are value types, so their value can't be null
. So this is strictly a C#-problem: there is simply no value for these properties to indicate that they don't exist. Instead, they assume a default value (e.g. false
for bool
and 0
for numeric types). A string
, on the other hand, is a reference type so it can be null.
Make the properties nullable You can use nullable fields in your models, e.g.:
class User {
public bool? GetMailNotifications { get; set; }
}
That way, the value type can have one of its valid values or be null
. This can, however, be clumsy to work with because you'll have to do null
checks and use myUser.GetMailNotifications.Value
or the myUser.GetMailNotifications.GetValueOrDefault
helper whenever you want to access the property.
Simply include the fields instead this doesn't answer the question of how to it, but there are at least three good reasons why it's a good idea to include them:
User
object around, it's desirable that the object is in a valid state. Otherwise, you might pass a partially hydrated object to a method which passes it further and at some point, someone attempts an operation that doesn't make sense because the object is incompleteSo the question is: why do you want to make all the effort of excluding certain fields?
Upvotes: 2