我有一些类型User的poco,我担心它的属性将来会改变。我有一个带Users集合的MongoDB来存储数据。它没有唯一性约束,我无法创建一个不幸的。我的应用程序从第三方存档源导入一堆旧用户,我希望能够将这些用户写入Mongo,但我不希望重复,也不希望在Match上替换用户数据,因为Mongo中的数据是实际的。基本上,我们可以通过匹配像a.Username == b.Username && a.Email == b.Email这样的过滤器或者类似的东西来定义用户重复,我不希望它与这个问题相关,我们可以说有一种方法可以判断用户a和b是否相同。
所以看起来我在这里唯一的选择就是使用upsert update和setoninsert。在c driver中有一个方法Builders<User>.Update.SetOnInsert<TField>(Expression<User,TField>, TField),但我必须多次调用它才能枚举所有属性。如果这些属性将来要改变,就必须有人更新这个方法,我不喜欢它。
有办法绕过这个问题吗?可能通过使用reflecion和PropertyInfo或者直接使用BsonDocument来实现?或者我漏掉了什么东西还有更简单的方法?提前谢谢。

最佳答案

好吧,其实没那么难:

    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);

08-28 03:56