自动生成对象 Id 的 MongoDB C# 是什么?

5

我用C#学习mongodb,我想创建一个包含实体列表记录,但子实体没有生成它的对象id。

下面是我的代码:

public class Curso
{
    [BsonId]
    public ObjectId _id { get; set; }

    [BsonElement("descripcion")]
    public string descripcion { get; set; }

    [BsonElement("horas")]
    public int horas { get; set; }

    [BsonElement("alumnos")]
    public IEnumerable<Alumno> alumnos { get; set; }

    public Curso()
    {

    }
}

学生实体:

public class Alumno
{
    [BsonId]
    public ObjectId _id { get; set; }

    [BsonElement("name")]
    public string name { get; set; }

    [BsonElement("age")]
    public int age { get; set; }
}

我插入了一个新的课程,自动生成的课程ID已经起作用,但是学生ID没有生成,而是被设置为"000000000000000000000000"

    public Curso create(Curso curso)
    {
        db.GetCollection<Curso>("curso").Save(curso);
        return curso;
    }

RESULT:

{ "_id" : ObjectId("5a766ec765583a0f90bc0edf"), "descripcion" : "JAVA + JPA", "horas" : 200, "alumnos" : [ { "_id" : ObjectId("000000000000000000000000"), "name" : "Catalina Castillo", "age" : 22 }, { "_id" : ObjectId("000000000000000000000000"), "name" : "Marcia Pardo", "age" : 45 }, { "_id" : ObjectId("000000000000000000000000"), "name" : "Will Smith", "age" : 24 } ] }
4个回答

14
每个 MongoDB 文档都应该有一个具有唯一值的 _id 字段。因此,当您传递带有零 _idCurso 文档时,MongoDB 会为您生成它。
然而对于嵌入式文档来说情况并非如此。对于 MongoDB 来说,嵌入式文档中的 _id 字段只是普通字段,就像 agename 字段一样。这就是为什么 MongoDB 不会费心为嵌入式文档填充 _id 并将它们保存为您传递的值,即零填充。
因此,您应该自己为 Alumno._id 生成值。您可以在 Alumno 构造函数中或在将文档插入数据库之前完成此操作:
public class Alumno
{
    [BsonId]
    public ObjectId _id { get; set; }

    [BsonElement("name")]
    public string name { get; set; }

    [BsonElement("age")]
    public int age { get; set; }

    public Alumno()
    {
        _id = ObjectId.GenerateNewId();
    }
}

2
您还可以使用以下属性声明属性:
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId? _id { get; set; }

这将生成一个id。

0
如果你需要在代码中使用Id字段,但又不想自己设置它,那么你可以使用BsonRepresentation和字符串Id。如果你的Id字段既不是ObjectId也不是在Id上,你可以使用[BsonId]。
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }

0
对我来说,令人惊讶的是,在mongodb数据库中,_id字段的表示方式取决于id/Id/_id字段的类型是字符串还是ObjectId。
例如,字符串类型的id: 字符串类型id示例 例如,ObjectId类型的id: ObjectId类型id示例 此外,当对一个带有ObjectId类型id的对象进行json序列化时,输出结果并不适合直接发送给浏览器。 示例序列化结果:
{
  "id": {
    "Timestamp": 1692982711,
    "Machine": 13655676,
    "Pid": -26385,
    "Increment": 8598747,
    "CreationTime": "2023-08-25T16:58:31Z"
  },
  "name": "test2"
}

这里是重现结果的代码:
record TestDoc1(string id, string name = "test1");
record TestDoc2(ObjectId id, string name = "test2");

[Fact]
public async Task MongoDbTest()
{
    var client = new MongoClient(_connectionUri);
    var testDB = client.GetDatabase($"testDB");
    var testCollection1 = testDB.GetCollection<TestDoc1>("testCollection1");
    var testCollection2 = testDB.GetCollection<TestDoc2>("testCollection2");
    
    var objectId = ObjectId.GenerateNewId();
    var docWithStringId = new TestDoc1(objectId.ToString());
    var docWithObjectId = new TestDoc2(objectId);
    var docWithObjectIdAsJson = JsonSerializer.Serialize(docWithObjectId, new JsonSerializerOptions { WriteIndented = true });
    Console.WriteLine(docWithObjectIdAsJson);
    await testCollection1.InsertOneAsync(docWithStringId, null);
    await testCollection2.InsertOneAsync(docWithObjectId, null);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接