我最近在我们的应用程序中遇到了下面的代码
var updateDefinition = new UpdateDefinitionBuilder<OverviewProfile>()
.Set(a => a.Advisors[-1].IsCurrent, advisor.IsCurrent);
在上面的代码中,Advisors
是List
,UpdateDefinitionBuilder
来自MongoDB驱动程序。
能告诉我在列表索引中使用-1吗?
在以下评论/答案后编辑
OverviewProfile
课程如下:
public class OverviewProfile: BaseInvestorProfile
{
//Other properties
public List<Advisor.View.Advisor> Advisors { get; set; }
public OverviewProfile(int id): base(id)
{
Advisors = new List<Advisor.View.Advisor>();
}
}
这就是工作代码。此代码根据条件将数据更新到mongodb。此类中没有其他方法,只有其他属性。
这是一个类,但对于多个类的属性也有相同的用法,即使我们添加新的List
属性并检查,它也能正常工作。
你正在使用UpdateDefinitionBuilder<T>.Set
的重载,期望Expression
。此表达式不是直接编译和执行,而是转换为本机mongodb语法,并用作mongo db查询的一部分(与实体框架或其他ORM如何将表达式转换为SQL相同)。这基本上是说“更新所有概述配置文件并设置第一个顾问的IsCurrent标志,该标志符合advisor.IsCurrent
值的标准”。因为mongodb允许负索引(意思是 - 相对于集合的结尾) - C#mongodb驱动程序可以将表达式转换为有效的mongodb查询(但请参阅下面的更新)。
更新。如上所述here,-1仍然对mongodb C#驱动程序有特殊意义。它将被转换为positional update operator $:
位置$运算符充当与查询文档匹配的第一个元素的占位符
例如:
var updateDefinition = new UpdateDefinitionBuilder<OverviewProfile>()
.Set(a => a.Advisors[-1].IsCurrent, false);
colleciton.UpdateOne(c => c.Advisors.Any(r => r.IsCurrent), updateDefinition);
将被转换为:
"updates": [{
"q": {
"Advisors": {
"$elemMatch": {
"IsCurrent": true
}
}
},
"u": {
"$set": {
"Advisors.$.IsCurrent": false // <- your expression
}
}
}
]
但是,相对于mongodb中的colleciton结尾的负指数含义仍然成立,因为除了-1之外的任何其他负指数(例如,-2)将被转换为这样的查询:
{ "$set" : { "Advisors.-2.IsCurrent" : false} }
如果a.Advisors
确实是List<T>
,那就没有用了。这会抛出一个ArgumentOutOfRangeException
。
更有可能的是,这是一些自定义类或List<T>
上的实现,其中-1
值传递给索引器意味着类似“默认”值。
无论是什么,我认为这是一个糟糕的设计,应该避免。