【问题标题】:MongoDB Driver c# DateTime AddHours Query InvalidOperationExceptionMongoDB Driver c# DateTime AddHours Query InvalidOperationException
【发布时间】:2021-06-01 09:24:38
【问题描述】:

我有一个计划集合,其中包含 startDate 和持续时间(以小时为单位)(totalDuration)

public class PlanningDTO
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public ObjectId Id { get; set; }
 
    [BsonElement("startDate")]
    public DateTime StartDate { get; set; }

    [BsonElement("totalDuration")]
    public int TotalDuration { get; set; }
}

我想获取包含在日期范围内的计划。

我在 .Net 3.1 和 MongoDriver 2.12.3 中使用 API

我尝试过类似的方法:

GetPlanningsInDateRange(DateTime startDate, DateTime endDate){ 
var filter = Builders<PlanningDTO>
            .Filter
            .Where(pp => pp.StartDate.AddHours(pp.TotalDuration) >= startDate && pp.StartDate <= endDate);

var planningsInRange = await Db.GetCollection<PlanningDTO>("Plannings").Find(filter).ToListAsync();
return planningsInRange;
            }

或使用 Mongo.Driver.LINQ

var planningsInRange = await Db.GetCollection<PlanningDTO>("Plannings").AsQueryablew<PlanningDTO>()
.Where(pp => pp.StartDate.AddHours(pp.TotalDuration) >= startDate && pp.StartDate <= endDate).ToListAsync();

但我得到的是错误:

System.InvalidOperationException: {document}{startDate}.AddHours(Convert({document}{totalDuration}, Double)) 不受支持。

如果我在没有 AddHours() 的情况下进行这种查询,它可以正常工作(没有错误),但这不是我想要的。

有什么想法吗?

【问题讨论】:

  • 我的猜测是,将 LINQ 转换为底层查询是 MongoDB 查询引擎的限制 - 它不知道如何将 AddHours() 转换为可以转换为查询的东西,因为它是.NET 方法。
  • 我想一定是这样的,mongo驱动的一些限制。但我找不到任何解决方法
  • 您的 DTO 是否允许更改?如果有,达到什么程度?
  • 拥有一个额外的属性“EndDate”也许是有益的?
  • 更改 DTO 是最后的选择。不会轻易被允许的

标签: c# mongodb linq


【解决方案1】:

我相信您可以通过如下所示的投影来做到这一点,但这比从一开始就将 EndDate 存储在数据库中效率低。

ProjectionDefinition<Plan, object> projection = @"
{
    _id: 1,
    startDate: 1,
    totalDuration: 1,
    ENDDATE: { $add: ['$startDate', { $multiply: ['$totalDuration', 3600000] }] }
}";

var filter = Builders<Plan>.Filter.Gte(p => p.StartDate, startDate);
    filter &= Builders<Plan>.Filter.Lte("ENDDATE", endDate);

var result = await collection.Aggregate()
    .Project(projection)
    .As<Plan>()
    .Match(filter)
    .ToListAsync();

【讨论】:

  • 感谢您的回答。但是当我使用它时,我有一个错误“元素'ENDDATE'与类planningDTO的任何字段或属性都不匹配。这是否意味着我必须使用EndDate属性创建一个新类,然后将其映射到我的DTO?跨度>
  • @frdrc 抱歉没有正确测试它。我已经用工作版本更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多