簡體   English   中英

將.NET Guid轉換為MongoDB ObjectID

[英]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所提到的,從GuidObjectId是有損的,但是根據你如何使用該字段,這可能不是問題。 上面使用前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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM