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

时间:2011-12-21 04:14:37

标签: c# mongodb driver

通过官方c#驱动程序将新文档插入mongodb之后,如何立即读回生成的_id,以便将其用作其他集合的“外来”键?我知道在sql server中我可以立即读回新插入行的标识列值,所以我需要mongodb中的类似功能。

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

5 个答案:

答案 0 :(得分:2)

你可以使用findAndModify命令进行upsert来实现同样的效果,而不是通过生成自己的id来完成相同的工作。 (为什么麻烦,有一个很好的理由10gen决定使用的方案 - 它可以轻松进行分片)

findAndModify命令允许您查找或升级(如果它不存在则创建)文档并返回该文档。

一般表格如下:

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

您可以详细了解here

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

答案 1 :(得分:0)

在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"}] 

这就是我可以制作新身份证的方式

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"}] 

答案 2 :(得分:0)

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

答案 3 :(得分:0)

在大多数驱动程序中,_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字段。因此,您通常只需保存BSONDocumentBSONSerializable),然后再将其读回。

请注意,有一个名为DBRef的规范有助于简化“外键”的实现。文档为here,在C#中,您需要查看DBRef类。

答案 4 :(得分:0)

与此处的其他答案一样,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"));

所以现在你可以创建一个对象&amp;坚持两行:

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

实际上,使用最新的驱动程序甚至不需要设置默认值约定,它已经具有此行为OOTB。无论如何,mongo都没有使用约定。