mongodb linq提供程序:十进制类型字段的行为不正确?

时间:2017-03-30 20:06:36

标签: c# mongodb linq

使用mongodb版本3.4.3,c#驱动程序(nuget MongoDb.Driver)版本2.4.3

给定一个类Amount的字段decimal的类,以及此类型的mongodb集合。查询数量大于或小于某个值的条目的集合会产生不正确的结果。将类型更改为' int'时,代码行为正确。在MongoDb中使用十进制字段时是否存在一些问题?

下面的示例代码说明了这个问题。

class C
{
    public int Id { get; set; }
    public string Description { get; set; }
    public decimal Amount { get; set; }
}

// assumes a locally installed mongodb 
var connectionstring = "mongodb://localhost:27017/test";
var mongo = new MongoClient(connectionstring);
var db = mongo.GetDatabase("test");

db.DropCollection("testcollection");
db.CreateCollection("testcollection");
var collection = db.GetCollection<C>("testcollection");

// populate with 2 instances (amount 1 and amount 10)

collection.InsertMany(new[]
{
    new C{Id = 1, Description = "small", Amount = 1},
    new C{Id = 2, Description = "large", Amount = 10},
});

// verify that the documents are indeed persisted as expected
var all = collection.AsQueryable().ToList();
Debug.Assert(all.Count == 2);
Debug.Assert(all[1].Amount == 10);

// the assert below inexplicably fails (the query returns no results)
var largerThan5 = collection.AsQueryable().Where(c => c.Amount > 5).ToList();
Debug.Assert(largerThan5.Count == 1);

1 个答案:

答案 0 :(得分:6)

那是因为它会将所有小数转换为字符串(因此它们将存储在mongo数据库的字符串列中)。当然,在这种情况下,您的gt比较将失败。关于这个问题有一个非常古老的问题here,因为&#34;按预期工作&#34;关闭。据我所知 - 在那些时候没有十进制BSON类型,所以行为是合理的。

现在here您可以看到版本3.4中有新的十进制BSON类型,实际上C#驱动程序已经支持它。但是,如果您只使用.NET decimal类型 - 它仍会将其转换为字符串,即使使用mongo 3.4也是如此。

你需要做什么(因为你正在运行3.4)是:

  1. 使用Amount

    装饰您的[BsonRepresentation(BsonType.Decimal128)]
    class C
    {
        public int Id { get; set; }
        public string Description { get; set; }
        [BsonRepresentation(BsonType.Decimal128)]
        public decimal Amount { get; set; }
    }
    
  2. 将功能兼容性版本设置为3.4,因为早期版本无法按照规定的here处理BSON十进制:

    db.adminCommand({setFeatureCompatibilityVersion: "3.4"})
    
  3. 之后,您的小数将被正确映射,查询将按预期工作。