1

So lets begin with the simple example. Me and my team are working at the school software project. We are using MongoDB to store products and we are using interfaces so we can change implementation in the future. Product looks like this.

interface IProduct
{
    long ID { get; set; }
    string Name { get; set; }
}

class MongoProduct : IProduct
{
    [BsonId]
    public long ID { get; set; }
    public string Name { get; set; }
}

We have interface for testing.

interface ITestProbe
{
    IQueryable<IProduct> FindProducts(Expression<Func<IProduct, bool>> condition);
}

And assume this implementation

class MongoRepository : ITestProbe
{
    public MongoRepository()
    {
        _client = new MongoClient();
        _server = _client.GetServer();
        _db = _server.GetDatabase(_dbName);
        _collection = _db.GetCollection(_collectionName);
    }

    public const string _dbName = "MongoPlayground";
    public const string _collectionName = "Products";

    protected MongoClient _client;
    protected MongoServer _server;
    protected MongoDatabase _db;
    protected MongoCollection _collection;

    public IQueryable<IProduct> FindProducts(System.Linq.Expressions.Expression<Func<IProduct, bool>> condition)
    {
        return _collection.AsQueryable<MongoProduct>().Where<IProduct>(condition);
    }
}

This won't work because of "Unable to determine the serialization information for the expression: p.Name." when you test it like this:

class Program
{
    static void GenerateProducts()
    {
        var _client = new MongoClient();
        var _server = _client.GetServer();
        var _db = _server.GetDatabase("MongoPlayground");
        var _collection = _db.GetCollection("Products");

        MongoProduct[] products = new MongoProduct[]{
            new MongoProduct(){ID=1,Name="A"},
            new MongoProduct(){ID=2,Name="B"},
            new MongoProduct(){ID=3,Name="C"},
            new MongoProduct(){ID=4,Name="D"}
        };

        foreach (var p in products)
        {
            _collection.Insert<MongoProduct>(p);
        }
    }

    static void Main(string[] args)
    {
        //GenerateProducts();
        MongoRepository r = new MongoRepository();
        var products = r.FindProducts(p => p.Name == "C");
        foreach (var p in products)
        {
            Console.WriteLine(p.Name);
        }
    }
}

The solution to this problem is to translate Expression from IProduct to MongoProduct (example how to do this is in antoher topic at stackoverflow How do I translate an expression tree of one type to a different expression type?

Then we can write:

var switched = Translate<IProduct, MongoProduct>(condition);
return _collection.AsQueryable<MongoProduct>().Where<MongoProduct>(switched);

So my question is is there another way how to do it? Am I something missing? I tried to google solution but found nothing. I dont understand why we can't use IProduct in the Where function when MongoProduct is of type IProduct. This 'translating' solution seems a little clunky to me.

Community
  • 1
  • 1
Martin
  • 303
  • 5
  • 14
  • I really don't know the solution, but have you tried the solution of this problem? http://stackoverflow.com/questions/15957582/enum-cant-be-deserialized-when-using-linq – user3354977 Feb 26 '14 at 09:20
  • You can't use ToEnumerable after AsQueryable in Mongo driver. – Martin Feb 26 '14 at 16:45

0 Answers0