Reputation: 1265
I'm very new to MongoDB, but have what I believed to be a very simple query.
I have a Protein object that inherits from IProtein (yes, my naming sucks)
public interface IProtein
{
int Count { get; set; }
DateTime Date { get; set; }
}
I want to return the FirstOrDefault
from the collection based on a date comparison of the Date
field of the protein object and Today
public IProtein GetProteinForDay(DateTime day)
{
var collection = _db.GetCollection<IProtein>(DB_COLLECTION);
var query = collection.AsQueryable<IProtein>()
.Where(p => p.Date == day.Date);
var protein = query.FirstOrDefault();
return protein;
}
Unfortunately, I've gone through so many different variations of trying to match dates using MongoDB (some using Linq, some not) that I've completely lost focus on how far I got with each one.
This is my current code, it returns the error Unable to determine the serialization information for the expression: p.Date
What is wrong with my query (yes, it probably is something very simple) and how do I actually compare dates with a MongoDB / Linq query?
Upvotes: 0
Views: 2990
Reputation: 8978
Well, It's disappointing that .net DateTime doesn't work seamlessly with MongoDB driver. I believe support should be baked into driver.
Anyway you'll need to take couple of steps to make .net and MongoDB work together.
1) Decorate Date
field in your interface with BsonDateTimeOptions
attribute to tell MongoDB driver how to serialize .net DateTime. See BsonDateTimeOptions Documentation
Interface should looks like
public interface IProtein
{
int Count { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
DateTime Date { get; set; }
}
2) In your GetProteinForDay
function, replace
var collection = _db.GetCollection<IProtein>(DB_COLLECTION);
var query = collection.AsQueryable<IProtein>()
.Where(p => p.Date == day.Date);
with
var collection = db.GetCollection<Protein>(DB_COLLECTION);
var query = collection.Find(p => p.Date == day);
Notice that, I have replaced interface IProtein
with concrete implementation of interface, in my case Protein
.
Update: Full program is attached as reference.
Source document:
{
_id: ObjectID('5964ebf315c46ab80b2c20f3),
Count: 10,
Date: '2017-07-11 00:00:00.000'
}
Test Program:
using System;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
namespace mongoT
{
public interface IProtein
{
ObjectId Id { get; set; }
int Count { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
DateTime Date { get; set; }
}
public class Protein : IProtein
{
public ObjectId Id { get; set; }
public int Count { get; set; }
public DateTime Date { get; set; }
public override string ToString()
{
return $"{nameof(Id)}: {Id}, {nameof(Count)}: {Count}, {nameof(Date)}: {Date}";
}
}
class Program
{
private static string DB = "ProteinsDB";
private static string COLLECTION = "Proteins";
static void Main(string[] args)
{
var result = GetProteinForDay(DateTime.Now.Date);
Console.WriteLine(result);
}
public static IProtein GetProteinForDay(DateTime day)
{
var client = new MongoClient();
var db = client.GetDatabase(DB);
var collection = db.GetCollection<Protein>(COLLECTION);
var query = collection.Find(p => p.Date == day.Date);
var protein = query.FirstOrDefault();
return protein;
}
}
}
Upvotes: 4