MongoDB C# 驱动程序 - 如何将 _id 存储为 ObjectId 但映射到字符串 Id 属性

mongodb

1个回答

写回答

l金不换vhb@@

2025-06-12 15:50

+ 关注

MongoDB
MongoDB

使用MongoDB C#驱动程序时,我们经常会遇到需要将_id字段存储为ObjectId类型,但同时又希望在实体类中使用字符串类型的Id属性来映射_id字段的情况。这种需求在一些特定的业务场景中非常常见,因此我们需要找到一种解决方案来满足这个需求。

在使用MongoDB C#驱动程序时,默认情况下,_id字段会被存储为ObjectId类型。而在实体类中,我们通常会定义一个字符串类型的Id属性来映射_id字段。为了实现这种映射,我们可以使用自定义的属性映射器来处理。

首先,我们需要创建一个自定义的属性映射器类,继承自BsonClassMapSerializer类。然后,在自定义的属性映射器类中,我们可以重写CreateMemberMap方法,来自定义_id字段的映射规则。

具体的实现代码如下所示:

csharp

public class CustomBsonClassMapSerializer<T> : BsonClassMapSerializer<T>

{

public CustomBsonClassMapSerializer(BsonClassMap<T> classMap) : base(classMap)

{

}

protected override BsonMemberMap CreateMemberMap(BsonMemberMap memberMap)

{

if (memberMap.MemberName == "_id")

{

memberMap = new BsonMemberMap(typeof(T).GetProperty("Id"))

{

MemberName = "_id",

SerializeMemberValue = value => value.ToString(),

DeserializeMemberValue = bsonValue => new ObjectId(bsonValue.AsString)

};

}

return base.CreateMemberMap(memberMap);

}

}

在上述代码中,我们重写了CreateMemberMap方法,并判断了成员名称是否为"_id"。如果是"_id"字段,我们创建了一个新的BsonMemberMap,并指定了成员名称为"_id",序列化和反序列化方法分别将字符串类型的Id属性转换为ObjectId类型的值,以及将ObjectId类型的值转换为字符串类型的Id属性。

接下来,我们需要在实体类上应用这个自定义的属性映射器。为此,我们可以使用BsonClassMap.RegisterClassMap方法来注册自定义的属性映射器。

下面是一个示例实体类的代码:

csharp

public class User

{

public string Id { get; set; }

public string Name { get; set; }

// other properties

}

然后,我们可以在应用程序启动时注册自定义的属性映射器,代码如下所示:

csharp

BsonClassMap.RegisterClassMap<User>(cm =>

{

cm.AutoMap();

cm.SetSerializer(new CustomBsonClassMapSerializer<User>(cm));

});

在上述代码中,我们使用了BsonClassMap.RegisterClassMap方法来注册自定义的属性映射器,并指定了要应用这个属性映射器的实体类类型。

通过以上的代码,我们就成功地将_id字段存储为ObjectId类型,同时使用字符串类型的Id属性来映射_id字段了。

案例代码:

下面是一个完整的案例代码,演示了如何使用自定义的属性映射器将_id字段存储为ObjectId类型,同时使用字符串类型的Id属性来映射_id字段。

csharp

using MongoDB.Bson;

using MongoDB.Bson.Serialization;

using MongoDB.Bson.Serialization.Serializers;

using MongoDB.Driver;

using System;

public class CustomBsonClassMapSerializer<T> : BsonClassMapSerializer<T>

{

public CustomBsonClassMapSerializer(BsonClassMap<T> classMap) : base(classMap)

{

}

protected override BsonMemberMap CreateMemberMap(BsonMemberMap memberMap)

{

if (memberMap.MemberName == "_id")

{

memberMap = new BsonMemberMap(typeof(T).GetProperty("Id"))

{

MemberName = "_id",

SerializeMemberValue = value => value.ToString(),

DeserializeMemberValue = bsonValue => new ObjectId(bsonValue.AsString)

};

}

return base.CreateMemberMap(memberMap);

}

}

public class User

{

public string Id { get; set; }

public string Name { get; set; }

// other properties

}

class Program

{

static void MAIn(string[] args)

{

BsonClassMap.RegisterClassMap<User>(cm =>

{

cm.AutoMap();

cm.SetSerializer(new CustomBsonClassMapSerializer<User>(cm));

});

var client = new MongoClient();

var Database = client.GetDatabase("test");

var collection = Database.Getcollection<User>("users");

var user = new User

{

Id = "1",

Name = "John Doe"

};

collection.InsertOne(user);

var retrievedUser = collection.Find(u => u.Id == "1").FirstOrDefault();

Console.WriteLine($"Retrieved user: {retrievedUser.Id} - {retrievedUser.Name}");

}

}

在上面的代码中,我们首先定义了一个CustomBsonClassMapSerializer类,继承自BsonClassMapSerializer类,并重写了CreateMemberMap方法来处理_id字段的映射规则。然后,我们定义了一个User类作为示例实体类,包含了一个字符串类型的Id属性和一个Name属性。在MAIn方法中,我们注册了自定义的属性映射器,并演示了如何使用自定义的属性映射器来存储和检索数据。

通过使用自定义的属性映射器,我们可以很方便地将MongoDB中的_id字段存储为ObjectId类型,同时在实体类中使用字符串类型的Id属性来映射_id字段。这样可以满足一些特定业务场景中的需求,并提供了更灵活的操作方式。在实际开发中,我们可以根据具体的需求和业务场景来使用自定义的属性映射器,以满足不同的数据映射需求。

举报有用(4分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号