c# - C# MongoDB 从填充模型更新定义
问题描述
我如何结合类型 C# 填充模型和 mongo 语言来创建更新请求?
我试试这个但得到类型错误:
var update = new ObjectUpdateDefinition<User>(user) & Builders<User>.Update.Inc(f => f.FindCount, 1);
全码:
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
});
推荐阅读
- cassandra - Cassandra 备份和恢复一致性
- json - 像 xslt / saxon 一样简单的 json 转换
- powershell - 使用 FILTER 与数组的任何成员进行比较
- wpf - 导航栏使用 WPF 错误(无法解析属性路径中的所有属性引用)
- android - 从 App-Widget 打开 Activity,打开最后一个 Activity
- rest - 如何实现 REST API 调用跟踪
- vue.js - Vagrant VirtualBox 本地开发环境、Ubuntu、Yarn、Vue CLI 3 - 问题
- android - 如果片段不是空的,如何加载片段 - Android?
- firebird - 如何将 Firebird 数据库与 Knime 连接?
- php - 如何在实时搜索栏中创建可点击的搜索结果