Mongodb中LINQ Where子句中的接口

时间:2014-02-24 23:00:55

标签: c# linq mongodb interface where-clause

让我们从简单的例子开始吧。我和我的团队正在学校的软件项目中工作。我们使用MongoDB来存储产品,我们正在使用接口,因此我们可以在将来更改实现。产品看起来像这样。

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

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

我们有测试界面。

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

并假设此实现

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);
    }
}

这不起作用,因为“无法确定表达式的序列化信息:p.Name。”当你像这样测试时:

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);
        }
    }
}

此问题的解决方案是将Expression从IProduct转换为MongoProduct(示例如何执行此操作是在stackoverflow How do I translate an expression tree of one type to a different expression type?

的其他主题中

然后我们可以写:

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

所以我的问题是,还有另外一种方法吗?我缺少什么?我试图谷歌解决方案但没有发现任何东西。我不明白为什么当MongoProduct是IProduct类型时我们不能在Where函数中使用IProduct。这种“翻译”解决方案对我来说似乎有点笨拙。

0 个答案:

没有答案