如何将.NET GUID转换为MongoDB ObjectID(在C#中)。另外,我可以将它再次转换回ObjectID中的相同GUID吗?
答案 0 :(得分:32)
您无法将ObjectId
转换为GUID
,反之亦然,因为它们是两种不同的东西(不同的大小,算法)。
您可以使用mongoDb _id
的任何类型,包括GUID
。
例如,在官方c#驱动程序中,您应指定属性[BsonId]
:
[BsonId]
public Guid Id {get;set;}
[BsonId]
public int Id {get;set;}
BSON ObjectID是12字节的值 由4字节时间戳组成 (自纪元以来的秒数),一个3字节 machine id,一个2字节的进程id和a 3字节计数器。请注意 时间戳和计数器字段必须是 与其余的不同,存储大端 BSON。这是因为他们是 逐字节比较,我们想要 确保大多增加订单。
GUID:
GUID的值表示为 一个32个字符的十六进制字符串, 如 {21EC2020-3AEA-1069-A2DD-08002B30309D}, 并且通常存储为128位 整数
答案 1 :(得分:6)
仅供参考您可以从ObjectId转换为Guid
public static Guid AsGuid(this ObjectId oid)
{
var bytes = oid.ToByteArray().Concat(new byte[] { 5, 5, 5, 5 }).ToArray();
Guid gid = new Guid(bytes);
return gid;
}
/// <summary>
/// Only Use to convert a Guid that was once an ObjectId
/// </summary>
public static ObjectId AsObjectId(this Guid gid)
{
var bytes = gid.ToByteArray().Take(12).ToArray();
var oid = new ObjectId(bytes);
return oid;
}
答案 2 :(得分:3)
虽然没有一个直接的答案,但请记住,没有。要求_id是一个ObjectID ---只有它是唯一的。
可以为_I'd设置任何有效类型,包括嵌入对象或。你应该没事(禁止任何唯一性违规)使用_ID的GUID;实际上,ObjectID实际上只是一个自定义GUID。
答案 3 :(得分:0)
如果要从头开始,则可以将“ Id”成员键入为Guid
而不是ObjectId
。这是首选,因为这样您的模型就不必引用MongoDB.Bson
,可以说不再使它成为POCO类。如果您将成员命名为“ Id”,则甚至不需要[BsonId]
属性,最好不要因为上述原因。
如果您已经在POCO类中使用ObjectId
并已经意识到了困难,则想更改“ Id”的类型(在您的类中),但无法更改(在您的数据中)“ _ id”的类型,您可以创建自定义序列化器:
public class SafeObjectIdSerializer: ObjectIdSerializer
{
public SafeObjectIdSerializer() : base() { }
public override ObjectId Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var bsonReader = context.Reader;
var bsonType = bsonReader.GetCurrentBsonType();
switch (bsonType)
{
case BsonType.Binary: {
var value = bsonReader
.ReadBinaryData()
.AsGuid
.ToString()
.Replace("-", "")
.Substring(0, 24);
return new ObjectId(value);
}
}
return base.Deserialize(context, args);
}
}
正如MiddleTommy所说,从Guid
到ObjectId
是有损耗的,但是取决于您使用该字段的方式,这可能不是问题。上面的代码使用前24个十六进制字符,并丢弃其余的8个字符。如果您存储的是随机ObjectId
值,而不是说一个用Int递增的ObjectId转换,那么应该没事。
如果您还想将ObjectId
编写为Guid
,则只要使用{{1} },但我可能错了,这可能取决于您的实现。该文档没有说任何一种方法。为此,您可以将此替代添加到上面的类中:
base.Deserialize()
要使您的全局反序列化器:
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, ObjectId value)
{
var bsonWriter = context.Writer;
var guidString = value
.ToString()
.Insert(8, "-")
.Insert(13, "-")
.Insert(18, "-")
.Insert(23, "-") + "00000000";
var asGuid = new Guid(guidString);
bsonWriter.WriteBinaryData(new BsonBinaryData(asGuid));
}
然后在只能调用一次的地方,例如您的Global.asax public class CustomSerializationProvider : IBsonSerializationProvider
{
public IBsonSerializer GetSerializer(Type type)
{
if (type == typeof(ObjectId))
{
return new SafeObjectIdSerializer();
}
//add other custom serializer mappings here
//to fall back on the default:
return null;
}
}
Application_Start()