[英]How to update a field “type-safe” in a deeply nested array with C# MongoDb driver?
我正在尝试更新深度嵌套数组中的各个字段。
public class Maker
{
public int Id { get; set; }
public List<Vehicle> Vehicles { get; set; }
}
public class Vehicle
{
public int Id { get; set; }
public int Price { get; set; }
public List<Part> Parts { get; set; }
}
public class Part
{
public int Id { get; set; }
public string Name { get; set; }
}
更新 1 级数组中的字段就像一个魅力。 更新 2 级数组中的字段失败。
public void UpdateNestedArrayFields()
{
var client = new MongoClient();
var db = client.GetDatabase("test");
var makers = db.GetCollection<Maker>("makers");
// Create a maker and add a vehicle
var newPart = new Part() { Id = 34, Name = "Wheel" };
var newVehicle = new Vehicle() { Id = 17, Price = 1000, Parts = new List<Part>() { newPart } };
var newMaker = new Maker() { Id = 5, Vehicles = new List<Vehicle>() { newVehicle } };
// Update vehicle's price (WORKS)
makers.FindOneAndUpdate(
m => m.Id == newMaker.Id && m.Vehicles.Any(v => v.Id == newVehicle.Id),
Builders<Maker>.Update.Set(m => m.Vehicles[-1].Price, 2000));
// Update part's name (**FAILS**)
makers.FindOneAndUpdate(
m => m.Id == newMaker.Id && m.Vehicles.Single(v => v.Id == newVehicle.Id).Parts.Any(p=> p.Id == newPart.Id),
Builders<Maker>.Update.Set(m => m.Vehicles[-1].Parts[-1].Name, "Tire"));
}
我知道不支持多个位置运算符,所以我的最后一行 (m.Vehicles[-1].Parts[-1].Name) 有点废话。
显然我不是唯一一个遇到这个问题的人,我找到了类似这样或那样的不同解决方案。 但是,它们都不是类型安全的。 生成的代码非常丑陋且容易出错。
所以我想知道:有没有办法重新设计我的代码,使其类型安全?
我正在使用 MongoDb 4.0.9 和 C# 驱动程序 2.11.5。
编辑(01-11-2020):对于任何感兴趣的人,我发现 Massimiliano Kraus 的这个非常好的扩展,它有点过时(2017 年),但仍在工作,结果证明是一个巨大的帮助。 谢谢你,马西米利亚诺! MongoDB.DeepUpdater.CSharp
还有一个类型化嵌套数组更新的其他可能且类型更多的版本。 它没有完全输入,但它更接近你的需要。
它也使用ArrayFilters
但以更多类型的方式
此代码直接来自我正在处理的应用程序。
var filter = Builders<EventModel>.Filter.Eq(s => s.Id, eventId);
var settingsPath = @$"{nameof(EventModel.EventLayout)}.{nameof(EventLayoutSetting.Pages)}.$[page].{nameof(Page.Components)}.$[component].{nameof(Component.Settings)}";
var update = Builders<EventModel>.Update.
Set(settingsPath, settings);
var dbResult = await eventsCollection.UpdateOneAsync(filter, update, new UpdateOptions
{
ArrayFilters = new List<ArrayFilterDefinition>
{
new BsonDocumentArrayFilterDefinition<BsonDocument> (new BsonDocument($"page.{nameof(Page.PageId)}",pageId)),
new BsonDocumentArrayFilterDefinition<BsonDocument> (new BsonDocument($"component.{nameof(Component.ComponentId)}",componentId))
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.