【问题标题】:mongodb linq provider: incorrect behavior for fields of type decimal?mongodb linq 提供程序:十进制类型的字段的行为不正确?
【发布时间】:2017-03-30 20:06:36
【问题描述】:

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

给定一个具有decimal 类型的字段Amount 的类,以及这种类型的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);

【问题讨论】:

  • 您是否尝试将[BsonRepresentation(BsonType.Decimal128)] 添加到Amount 字段?
  • @Veeram 我试过了,尝试插入时失败了。
  • @Evk 我无法针对 3.4 服务器对其进行测试。我知道它会因您在 3.2 中的帖子中提到的错误而失败,这是预期的。我期待它可以在 3.4 上运行。
  • @Veeram,你是对的。我确实针对 3.4 进行了测试,但我错过的是 BSON 十进制需要设置 setFeatureCompatibilityVersion,如果没有它,它仍然会失败,并出现与 3.2 中相同的错误。但是使用该设置它可以按预期工作,所以我更新了我的答案。

标签: c# mongodb linq


【解决方案1】:

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

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

你需要做的(因为你运行的是 3.4)是:

  1. [BsonRepresentation(BsonType.Decimal128)]装饰你的Amount

    class C
    {
        public int Id { get; set; }
        public string Description { get; set; }
        [BsonRepresentation(BsonType.Decimal128)]
        public decimal Amount { get; set; }
    }
    
  2. 将功能兼容版本设置为 3.4,因为之前的版本无法处理 BSON 十进制,如 here 所述:

    db.adminCommand({setFeatureCompatibilityVersion: "3.4"})
    

之后,您的小数点将被正确映射并且查询将按预期工作。

【讨论】:

  • 谢谢你的回答,但是哇。哇。从 C# / .Net 的角度来看,这是非常不直观的......如果你问我,这完全是错误的。我会说驱动程序应该抛出一个异常,而不是默默地允许查询但返回错误的结果。
  • 是的,我同意,虽然我会说它不应该允许映射小数,至少在 3.4 之前,因为默默地将它们映射到字符串也不是很好的行为。
猜你喜欢
  • 2012-12-01
  • 2015-12-09
  • 2021-11-28
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-27
相关资源
最近更新 更多