我有一些类型为User
的POCO,我有些担心其属性将来会发生变化。我有一个带有Users
集合的mongodb来存储数据。它没有唯一性限制,我不能创造一个不幸的。我的应用程序从第三方存档源导入了一堆旧用户,我希望能够将这些用户写入mongo,但我不想要重复项,我不想在匹配时替换用户数据因为mongo中的数据是实际的。基本上我们可以通过匹配过滤器来定义用户副本,例如a.Username == b.Username && a.Email == b.Email
或类似的东西,我不希望它与这个问题相关,我们只是说那里我们可以告诉我们的方式如果用户A和B相同。
因此,我似乎唯一的选择是使用SetOnInsert进行upsert更新。在C#驱动程序中有一个方法Builders<User>.Update.SetOnInsert<TField>(Expression<User,TField>, TField)
,但我必须多次调用它来枚举所有属性。如果将来这些属性发生变化,有人必须更新此方法,我不喜欢它。
有没有办法绕过这个问题?也许通过使用reflecion和PropertyInfo
或直接与BsonDocument
合作?或者也许我错过了一些东西并且有更简单的方法吗?提前谢谢。
答案 0 :(得分:2)
好的,毕竟不是那么难:
var updates = new List<WriteModel<User>>();
foreach (User appUser in users)
{
FilterDefinition<User> filter = Builders<User>.Filter.Eq(x => x.Username, appUser.Username) & ...
var bsonDoc = appUser.ToBsonDocument();
UpdateDefinition<User> updateDefinition = new UpdateDefinitionBuilder<User>().Unset("______"); // HACK: I found no other way to create an empty update definition
foreach (var element in bsonDoc.Elements)
{
if (element.Name == "_id" || element.Value == BsonNull.Value)
continue;
updateDefinition = updateDefinition.SetOnInsert(element.Name, element.Value);
}
UpdateOneModel<User> update = new UpdateOneModel<User>(filter, updateDefinition) { IsUpsert = true };
updates.Add(update);
}
MongoConnectionHelper.Database.GetCollection<User>("Users").BulkWrite(updates);