如何使用官方的c#驱动程序从mongo中读取插入后自动生成的ID

本文关键字:插入 读取 自动生成 ID 官方 何使用 驱动程序 mongo | 更新日期: 2023-09-27 18:18:39

在您通过官方c#驱动程序插入新文档到mongodb后,如何立即读取生成的_id,以便我可以将其用作其他集合的"外"键?我知道在SQL服务器中,我可以立即读回新插入行的身份列值,所以我需要mongodb中的类似功能。

由于mongo生成的_id不是对象的实际成员,假设您需要对通用bsondocument做一些事情?

如何使用官方的c#驱动程序从mongo中读取插入后自动生成的ID

您可以使用findAndModify命令执行一个upsert,以获得与生成您自己的id相同的效果,而且工作量更少。(为什么要麻烦,有一个很好的理由让10gen决定使用的场景——它使分片变得容易)

findAndModify命令允许您查找或upsert(如果不存在则创建)文档并返回相同的文档。

一般形式如下:

db.runCommand( { findAndModify : <collection>, <options> } )

你可以在这里阅读更多。

除了upsert选项之外,您还需要使用new选项,以便返回新创建的对象。

如果您需要_id,您可以自己生成它并在文档上手动设置。

在MongoDB中,id(通常)在客户端生成。你可以自己生成一个,使用适当的驱动程序调用,放到文档中,它会被保存。

我没有使用c#驱动程序,但是Ruby驱动程序为我做了所有的工作。

ruby-1.9.3-p0 :027 >   obj = coll.insert({'foo' => 'bar'})
 => BSON::ObjectId('4ef15e7f0ed4c00272000001') 
ruby-1.9.3-p0 :030 > coll.find.to_a
 => [{"_id"=>BSON::ObjectId('4ef15e7f0ed4c00272000001'), "foo"=>"bar"}] 

这是我如何创建一个新的ID

ruby-1.9.3-p0 :039 >   newid = BSON::ObjectId.new
 => BSON::ObjectId('4ef15f030ed4c00272000002') 
ruby-1.9.3-p0 :040 > coll.insert({_id: newid, test: 'test'})
 => BSON::ObjectId('4ef15f030ed4c00272000002') 
ruby-1.9.3-p0 :041 > coll.find.to_a
 => [{"_id"=>BSON::ObjectId('4ef15e7f0ed4c00272000001'), "foo"=>"bar"},     {"_id"=>BSON::ObjectId('4ef15f030ed4c00272000002'), "test"=>"test"}] 

在大多数驱动程序中,_id字段实际上是在发送到服务器之前在客户端生成的。MongoDB不使用"自动增量"ID,所以你可以实际生成一个随机ID,并告诉服务器"使用这个"

在c#中,代码是这样的:
var id = ObjectId.GenerateNewId();

所以你可以创建一个BSON文档并保存它:

var toSave = new BsonDocument {
    { "_id", ObjectId.GenerateNewId() },
    { "data", "my data" }
};
db.collection.Save(toSave);

然而,默认情况下,当您.Save()一个文档时,这将更新_id字段。因此,您通常可以保存BSONDocument (BSONSerializable),然后再读取它。

请注意,有一个名为DBRef的规范有助于简化"外键"的实现。文档在这里,在c#中,你会想看看DBRef类。

与这里的其他答案一样,id是在客户端分配的。您可以做的是创建一个默认值约定,如果尚未设置,则在插入期间生成一个新ID。

public class DefaultValueConvention : MongoDB.Bson.Serialization.Conventions.IDefaultValueConvention
{
    public object GetDefaultValue(MemberInfo memberInfo)
    {
        var type = memberInfo.MemberType == MemberTypes.Property
                       ? ((PropertyInfo) memberInfo).PropertyType
                       : ((FieldInfo) memberInfo).FieldType;
        if (type.IsSubclassOf(typeof(ObjectId)))
            return ObjectId.GenerateNewId();
        else
            return null;
    }
}

并设置驱动程序使用这个约定:

var profile = new ConventionProfile();
profile.SetDefaultValueConvention(new DefaultValueConvention());
BsonClassMap.RegisterConventions(profile, x => x.FullName.StartsWith("ConsoleApplication"));

现在你可以创建一个对象&用两行保存:

var animal = new Animal {Name = "Monkey", PercentDeviationFromHumans = 2.01};
db["animals"].Save(animal);

实际上,对于最新的驱动程序,您甚至不需要设置默认值约定,它已经有这种行为了。无论如何,mongo中没有充分利用约定。