【问题标题】:how to read back out the auto generated ID from mongo after insertion using official c# driver?使用官方 c# 驱动程序插入后如何从 mongo 中读取自动生成的 ID?
【发布时间】:2011-12-21 04:14:36
【问题描述】:

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

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

【问题讨论】:

    标签: c# mongodb driver


    【解决方案1】:

    您可以使用 findAndModify 命令执行 upsert 以实现同样的效果,而工作量比生成您自己的 id 少。 (何必呢,10gen 决定使用的场景有一个很好的理由——它可以轻松进行分片)

    findAndModify 命令可让您查找或更新插入(如果不存在则创建)文档并返回该文档。

    一般形式如下:

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

    您可以阅读更多关于它的信息here

    除了 upsert 选项之外,您还想使用 new 来取回新创建的对象。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

          在大多数驱动程序中,_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 类。

          【讨论】:

            【解决方案5】:

            就像这里的其他答案所说,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"));
            

            所以现在您可以创建一个对象并将其保存在 2 行中:

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-03
              • 2019-12-10
              • 1970-01-01
              • 2019-09-07
              • 1970-01-01
              • 2012-10-31
              相关资源
              最近更新 更多