0

I need to keep a history of users' API calls. for this, I'm using MongoDB and C# driver.

Here is my mongo model class:

public class UsageModel
{
    [BsonIgnore]
    public static readonly string CollectionName = "ApiUsage";

    [BsonRequired]
    public string User { get; set; }

    [BsonRequired, BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
    public Dictionary<DateTime, int> History  { get; private set; }

    public static IMongoCollection<UsageModel> Collection
    {
        get => MongoDb.Database.GetCollection<UsageModel>(CollectionName);
    }

    public static void IncrementTodayStats(string user)
    {
        var filter = Builders<UsageModel>.Filter.Eq(doc => doc.User, user);
        var update = Builders<UsageModel>.Update.
            SetOnInsert(doc => doc.History[DateTime.Now.Date], 0).
            Inc(doc => doc.History[DateTime.Now.Date], 1);
        var res = Collection.UpdateOne(filter, update);
    }
}

The problem is when I call IncrementTodayStats I get this Exception:

Unable to determine the serialization information for doc => doc.History.get_Item(DateTime.Now.Date).

I don't know what I'm missing as I don't have much experience with MongoDB and Serialization, and as this answer advises I have put BsonDictionaryOptions decorator.

I should mention that prior to incrementing History[DateTime.Now.Date] I make sure that UsageModel containing this dictionary has been created and I've used SetOnInsert in case the entry for DateTime.Now.Date has not been present in the dictionary before this request.

Any help is greatly appreciated.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Ho'jat Kaveh
  • 123
  • 1
  • 8
  • Do you need the date to include hours, minutes, and seconds? You are useing Date which truncates the fractional part of the day. Do the entry for the date get put into the dictionary at the beginning of the day of the end of the day? You may want to try yesterday DateTime.Now.Date.AddDays(-1) – jdweng Nov 28 '18 at 12:06
  • @jdweng I just need the year, month and day parts of DateTime for my task. I can make a string like YY-MM-DD and change the type of dictionary key to string but the problem still persists. – Ho'jat Kaveh Nov 28 '18 at 12:17
  • I think the issue is with Update. Update only works if the date is already in the database. If the date doesn't exist then you need to use insert. It looks like you added the insert method. Does Insert work? – jdweng Nov 28 '18 at 13:18

1 Answers1

0

If you use LINQ query, the Mongo try to parse it, and build a query. If the LINQ query does not contain any client side infomation, then the whole query processing is hapenig in server side. Any other cases the driver receive the WHOLE data sete, and make an evaulation in client side. This parsing mechanism, is not able to parse the the DateTime.Now.Date, beasue it seems a property, but basiacalyy it is function calling.

Please use a variable instead of it.

public static void IncrementTodayStats(string user)
{
    DateTime today = DateTime.Now.Date;

    var filter = Builders<UsageModel>.Filter.Eq(doc => doc.User, user);
    var update = Builders<UsageModel>.Update.
        SetOnInsert(doc => doc.History[today], 0).
        Inc(doc => doc.History[today], 1);
    var res = Collection.UpdateOne(filter, update);
}
György Gulyás
  • 1,290
  • 11
  • 37