C#MongoDB从已填充的模型中更新定义



如何将C#填充模型和mongo语言结合起来创建更新请求?

我尝试了这个,但得到类型错误:

var update = new ObjectUpdateDefinition<User>(user) & Builders<User>.Update.Inc(f => f.FindCount, 1);

FullCode:

var user = new Model
{
Email = email,
Language = language,
Password = password,
// +17 fields
};

// how i can convert all fields to set? and join with query Inc (like AllFieldToSet)? 
var update = user.AllFieldToSet() & Builders<User>.Update.Inc(f => f.FindCount, 1);

Models.FindOneAndUpdate<Model>(
f => f.Email == email, 
update, 
new FindOneAndUpdateOptions<Model> {IsUpsert = true});

首先,我想问一下为什么一次更新这么多字段,这会对性能和可扩展性产生重大影响,尤其是当您的集合包含索引、复制和/或分片时。每当您必须更新索引字段时,它也需要更新索引。

有多种解决方案:

ReplaceOne:Inc只增加值,这可以在模型中手动完成:FindCount++

手动构建更新操作符:只需使用他们提供的构建器手动构建

使用反射编写自己的扩展就我个人而言,我喜欢类型安全,但你可以使用我编写的这个扩展(你只需要扩展它并构建空检查等(

public static class UpdateBuilderExtensions
{
public static UpdateDefinition<TDocument> SetAll<TDocument, TModel>(this UpdateDefinition<TDocument> updateBuilder, TModel value, params string[] excludeProperties)
{
foreach (var property in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => excludeProperties?.Contains(x.Name) == false))
updateBuilder = Builders<TDocument>.Update.Combine(updateBuilder.Set(property.Name, property.GetValue(value)));
return updateBuilder;
}
}

使用方法:您必须排除已经设置的属性,并且必须排除BsondId字段(如果您没有手动设置(

var update = Builders<User>.Update.Inc(x => x.FindCount, 1).SetAll(model, nameof(model.Id), nameof(model.FindCount));
Models.UpdateOne(x => x.Email== "some-email", update, new UpdateOptions
{
IsUpsert = true
});

最新更新