C# linq driver throws null reference exception for interface based repository (entity)

256 views
Skip to first unread message

Aurimas Neverauskas

unread,
May 30, 2012, 9:18:50 AM5/30/12
to mongodb...@googlegroups.com
Hi,

I've got some strange behaviour when using linq (1.4.2) queries in repository. If my repository generic parameter has interface clause I got exception on queries. If I use abstract class or normal class instead everything is OK. Here's my test that fails but if we change 'where T : IEntity' with 'where T : Entity' or make IEntity abstract class everything works. Is it a bug or what?

using System;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;

namespace MongoDbTest
{
class Program
{
static void Main()
{
var entity = new Entity();
var repository = new Repository<Entity>();
repository.Save(entity);
repository.Get(entity.Id);
}
}

public class Repository<T> where T : IEntity
{
private readonly MongoCollection<T> collection; 

public Repository()
{
var server = MongoServer.Create("mongodb://localhost/?safe=true");
var database = server.GetDatabase("local");
collection = database.GetCollection<T>(typeof(T).Name);
}

// throws null reference exception
public T Get(ObjectId id)
{
return collection.AsQueryable().Single(x => x.Id == id);
}

public void Save(T entity)
{
collection.Save(entity);
}
}

public interface IEntity
{
ObjectId Id { get; set; }
}

public class Entity : IEntity
{
public DateTime Date { get; set; }

public ObjectId Id { get; set; }
}
}



Aurimas Neverauskas

unread,
May 30, 2012, 9:38:29 AM5/30/12
to mongodb...@googlegroups.com
Also I've found another possible bug. After record retrieval the date field value was decreased by my UTC difference. Keeping to save and to retrieve value it was decreasing on every step till the minimum date value. For example from my test program I've got this output 'Original date: 5/30/2012 4:37:34 PM, entity date: 5/30/2012 1:37:34 PM'. It doesn't depend on my previous post with interface as I got this change in any case. Here's the code that was used to reproduce this date anomaly.

using System;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;

namespace MongoDbTest
{
class Program
{
static void Main()
{
var entity = new Entity { Date = DateTime.Now };
var repository = new Repository<Entity>();
repository.Save(entity);

var repository2 = new Repository<Entity>();
var entity2 = repository2.GetSafe(entity.Id);
Console.WriteLine("Original date: {0}, entity date: {1}", entity.Date, entity2.Date);
Console.ReadKey();
}
}

public class Repository<T> where T : IEntity
{
private readonly MongoCollection<T> collection; 

public Repository()
{
var server = MongoServer.Create("mongodb://localhost/?safe=true");
var database = server.GetDatabase("local");
collection = database.GetCollection<T>(typeof(T).Name);
}

// throws null reference exception
public T Get(ObjectId id)
{
return collection.AsQueryable().Single(x => x.Id == id);
}

public T GetSafe(ObjectId id)
{
return collection.AsQueryable().ToList().Single(x => x.Id == id);

Robert Stam

unread,
May 30, 2012, 10:07:29 AM5/30/12
to mongodb...@googlegroups.com
It's best to ask a single question per thread and start a new thread when you have an additional question.

Regarding your first question, I am able to reproduce it using the 1.4.2 version of the C# driver but not with the master branch from github, so this particular issue has been fixed since 1.4.2.

Regarding your second question, the BSON spec requires that all DateTimes be stored in UTC, so all drivers convert local times to UTC when they are stored in the database. If you change your Console.WriteLine statement to:

     Console.WriteLine("Original date: {0}, entity date: {1}", entity.Date.ToString("o"), entity2.Date.ToString("o")); // added ToString("o")

so that you can see the TimeZone offset of the DateTime the output becomes:

Original date: 2012-05-30T10:03:54.9240513-04:00, entity date: 2012-05-30T14:03:54.9240000Z

Those two DateTime value are the same instant in time, just that the first is in LocalTime and the second is in UTC.

The recommended approach is that your data always be in UTC and that you only convert to and from local time when displaying a DateTime to the user.

Aurimas Neverauskas

unread,
May 30, 2012, 11:19:48 AM5/30/12
to mongodb...@googlegroups.com
Thx, great answers.

1. Master branch works as expected.
2. Got it. So I guess it's intention is to evade daylight savings problem.
Reply all
Reply to author
Forward
0 new messages