[英]Convert .NET Guid to MongoDB ObjectID
如何將.NET GUID轉換為MongoDB ObjectID(在C#中)。 另外,我可以將它再次轉換回ObjectID中的相同GUID嗎?
你不能將ObjectId
轉換為GUID
,反之亦然,因為它們是兩個不同的東西(不同的大小,算法)。
您可以為mongoDb _id
使用任何類型,包括GUID
。
例如,在官方c#驅動程序中,您應該指定屬性[BsonId]
:
[BsonId]
public Guid Id {get;set;}
[BsonId]
public int Id {get;set;}
ObjectId :
BSON ObjectID是一個12字節的值,由4字節時間戳(自紀元以來的秒數),3字節機器ID,2字節進程ID和3字節計數器組成。 請注意,與BSON的其余部分不同,時間戳和計數器字段必須以big endian存儲。 這是因為它們是逐字節比較的,我們希望確保大多增加訂單。
GUID :
GUID的值表示為32個字符的十六進制字符串,例如{21EC2020-3AEA-1069-A2DD-08002B30309D},通常存儲為128位整數
僅供參考您可以從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;
}
雖然不是一個直接的答案,但請記住,沒有。要求_id是一個ObjectID ---只是它是唯一的。
可以為_I'd設置任何有效類型,包括嵌入對象或。 你應該沒事(禁止任何唯一性違規)使用_ID的GUID; 實際上,ObjectID實際上只是一個自定義GUID。
如果您從頭開始創建所有內容,則可以將“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
編寫,只要你回到base.Deserialize()
,它似乎不會傷害任何混合“_id”類型的東西,但我可能是錯的,這可能很重要取決於您的實施。 文檔沒有說明這種或那種方式。 為此,您可以將此覆蓋添加到上述類:
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));
}
為了使你的全局解串器:
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;
}
}
然后在某個地方只調用一次,就像你的Global.asax Application_Start()
BsonSerializer.RegisterSerializationProvider(new CustomSerializationProvider());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.