我必须将Convert Int32转换为Guids,这就是我想出来的。
public static class IntExtensions
{
public static Guid ToGuid(this Int32 value)
{
if (value >= 0) // if value is positive
return new Guid(string.Format("00000000-0000-0000-0000-00{0:0000000000}", value));
else if (value > Int32.MinValue) // if value is negative
return new Guid(string.Format("00000000-0000-0000-0000-01{0:0000000000}", Math.Abs(value)));
else //if (value == Int32.MinValue)
return new Guid("00000000-0000-0000-0000-012147483648"); // Because Abs(-12147483648) generates a stack overflow due to being > 12147483647 (Int32.Max)
}
}
但它有些丑陋。有人有更好的主意吗?
更新
是的,我知道整件事情很难看,但我失去了想法。 问题是。我正在获取数据并且必须将其存储到表中我无法更改。发送数据主键是Int,而我必须存储的表主键是Guid。 问题是我必须了解发件人正在谈论的对象,但只能将其存储为Guid。
更新2:
好的,我知道我必须在这里提供更多信息。我是一个接收数据的Web服务,必须将数据传递给我无法控制的接口。所以我既不能模拟收到的数据,也不能模拟我必须发送数据的(接口)数据库。另外,我必须以某种方式映射这两个东西,以便我能以某种方式更新项目。 叹息
答案 0 :(得分:57)
这是一种简单的方法:
public static Guid ToGuid(int value)
{
byte[] bytes = new byte[16];
BitConverter.GetBytes(value).CopyTo(bytes, 0);
return new Guid(bytes);
}
您可以更改复制的位置(将索引从0更改为12)。这实际上取决于你想如何定义这种不寻常的“int to Guid”转换。
答案 1 :(得分:25)
如果出现同样的问题,需要一个Int to Guid然后再回到Int。使用int ID的旧数据但处理函数需要Guid。编写额外函数和DB更改的代码很少。更容易以Guid形式传递Int iD,因为它知道它不会将其用作最终的保存Guid。保存是一个插入,所以它最终得到了一个新的Guid。
Heres是上面的代码和另一篇关于Guids to the int并让Int退出的帖子的想法。
public static Guid Int2Guid(int value)
{
byte[] bytes = new byte[16];
BitConverter.GetBytes(value).CopyTo(bytes, 0);
return new Guid(bytes);
}
public static int Guid2Int(Guid value)
{
byte[] b = value.ToByteArray();
int bint = BitConverter.ToInt32(b, 0);
return bint;
}
此Guid2Int只应传递来自Int。
的Guid答案 2 :(得分:6)
您可以从int获取数字并对其进行格式化,使它们看起来像GUID,但这不会使结果成为GUID。 GUID基本上是一个16字节的数字,使用保证数字唯一的算法计算。您可以在世界上的每台计算机上整天生成GUID,而不是重复(至少这是理论上的)。重新格式化的int不是唯一的,它绝对不是GUID。
答案 3 :(得分:1)
我还需要将数据库的主键(uint)编码为GUID。关于是否使用单元作为主键或Guid有很多讨论,我不会在这里进入,但我使用uint作为主键,使用guid作为列,我想编码主要键入guid,然后从guid中取回。
以下解决方案将一个24位主键(一个uint)编码为Guid,并将其解码回来。它在uint上使用DES加密。我认识到这个问题需要32位int,这适用于24位uint,但32可以通过连接两个GUID来实现,最高有效24位,一个带有最低有效24位,总共48位。该算法已经过全面测试,可用于int,但未针对负数进行测试。
GUID格式为32位,可以用连字符分隔,并包括大括号:00000000-0000-0000-0000-000000000000(D),即8-4-4-12个字符,即4-2-2-作为一个字节的6个字节被编码为2个字符。存在其他格式的GUID。
3字节uint加密为8字节代码,从第5个字节开始写入guid(这是Guid的第10个字符,忽略括号和' - '分隔符)。让我们来' z'表示编码的int,0表示任何其他十六进制字符。结果编码的GUID是
00000000-zzzz-zzzz-zzzz-zzzz00000000
请注意,此后GUID可能不是全局唯一的。但是,鉴于GUID对主键进行编码,它对于您的主键将是唯一的,并且在没有加密密钥的情况下从GUID中提取uint将非常困难....尽管DES加密是安全的。
public void Test()
{
Guid NewG = Guid.NewGuid();
Guid EnryptedGuid = Utility.EncodeInt24InGUID(NewG, Num);
uint RestoredUint = Utility.DecodeInt24FromGUID(EnryptedGuid);
}
public static Guid EncodeInt24InGUID(Guid guid, uint x)
{
if (x >= Math.Pow(2, 24))
throw new ArgumentOutOfRangeException("Unsigned integer is greater than 24bit");
string strGuid = guid.ToString();
strGuid = Utility.RemoveChars(strGuid, "-{}");//Remove any '-' and '{}' characters
byte[] bytes = BitConverter.GetBytes(x);
var encryptedarray = Cypher.EncryptDES(bytes, Cypher.Key);
string EncryptedGuid = WriteBytesToString(strGuid, encryptedarray, 9);
Guid outg;
Guid.TryParse(EncryptedGuid, out outg);
return outg;
}
从此处Removing characters from strings with LINQ
复制/改编RemoveCharsWriteBytesToString如下所示
public static string WriteBytesToString(string Input, byte[] bytes, int start)
{
StringBuilder g = new StringBuilder(Input);
string temp;
int ByteNum = 0;
int CharPos = start;
int NumBytes = (int)bytes.LongLength;
for (int i = 0; i < NumBytes; i++)
{
temp = string.Format("{0:x2}", bytes[ByteNum++]);
g[CharPos++] = (temp.ToCharArray())[0];
g[CharPos++] = (temp.ToCharArray())[1];
}
return g.ToString();
}
public static uint DecodeInt24FromGUID(Guid guid)
{
string strGuid = guid.ToString();
strGuid = Utility.RemoveChars(strGuid, "-{}");
byte[] EncryptedBytes = GetBytesFromString(strGuid, 9,8);
var decrypted = Cypher.DecryptDES(EncryptedBytes, Cypher.Key);
uint DecryptedUint = BitConverter.ToUInt32(decrypted, 0);
return DecryptedUint;
}
GetBytesFromString。请注意,字节从第9个索引开始,并且在调用函数中硬编码为8个字节。请参阅GUID格式的注释
public static byte[] GetBytesFromString(string Input, int start, int NumBytes)
{
StringBuilder g = new StringBuilder(Input);
byte[] Bytes = new byte[NumBytes];
string temp;
int CharPos = start;
for (int i = 0; i < NumBytes; i++)
{
temp = g[CharPos++].ToString();
temp += g[CharPos++].ToString();
Bytes[i] = byte.Parse(temp, System.Globalization.NumberStyles.HexNumber);
}
return Bytes;
}
从这里https://www.codeproject.com/Articles/5719/Simple-encrypting-and-decrypting-data-in-C复制网络类,并适应DES加密。它完整地粘贴在下面
using System.IO;
using System.Security.Cryptography;
namespace UtilityLib
{
// This class is adapted from https://www.codeproject.com/Articles/5719/Simple-encrypting-and-decrypting-data-in-C
public static class Cypher
{
public static string Key = "Asd9847Fg85ihkn52s";
// Encrypt a byte array into a byte array using a key and an IV
public static byte[] EncryptDES(byte[] clearData, byte[] Key, byte[] IV)
{
// Create a MemoryStream to accept the encrypted bytes
MemoryStream ms = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = Key;
alg.IV = IV;
CryptoStream cs = new CryptoStream(ms,alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(clearData, 0, clearData.Length);
cs.Close();
byte[] encryptedData = ms.ToArray();
return encryptedData;
}
public static byte[] EncryptDES(byte[] clearData, string Password)
{
PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
return EncryptDES(clearData, pdb.GetBytes(24), pdb.GetBytes(8));
}
public static byte[] DecryptDES(byte[] cipherData, byte[] Key, byte[] IV)
{
MemoryStream ms = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = Key;
alg.IV = IV;
CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherData, 0, cipherData.Length);
cs.Close();
byte[] decryptedData = ms.ToArray();
return decryptedData;
}
public static byte[] DecryptDES(byte[] cipherData, string Password)
{
PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
return DecryptDES(cipherData, pdb.GetBytes(24), pdb.GetBytes(8));
}
}
}
答案 4 :(得分:0)
我将更进一步。
有时需要提出一种在int
和Guid
之间来回移动的方式。添加两个或什至四个int
的复合ID进行混合。
我想到了:
[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct GuidToInt32 :
IEquatable<GuidToInt32>
{
public static readonly GuidToInt32 Empty;
[FieldOffset(0)]
private readonly Guid guidValue;
[FieldOffset(sizeof(int) * 0)]
private readonly int int32Value1;
[FieldOffset(sizeof(int) * 1)]
private readonly int int32Value2;
[FieldOffset(sizeof(int) * 2)]
private readonly int int32Value3;
[FieldOffset(sizeof(int) * 3)]
private readonly int int32Value4;
public GuidToInt32(Guid guidValue)
{
this.int32Value1 = default;
this.int32Value2 = default;
this.int32Value3 = default;
this.int32Value4 = default;
this.guidValue = guidValue;
}
public GuidToInt32(int int32Value1, int int32Value2 = default, int int32Value3 = default, int int32Value4 = default)
{
this.guidValue = default;
this.int32Value1 = int32Value1;
this.int32Value2 = int32Value2;
this.int32Value3 = int32Value3;
this.int32Value4 = int32Value4;
}
public Guid GuidValue => this.guidValue;
public int Int32Value1 => this.int32Value1;
public int Int32Value2 => this.int32Value2;
public int Int32Value3 => this.int32Value3;
public int Int32Value4 => this.int32Value4;
public static bool operator ==(GuidToInt32 leftValue, GuidToInt32 rightValue)
{
return leftValue.guidValue == rightValue.guidValue;
}
public static bool operator !=(GuidToInt32 leftValue, GuidToInt32 rightValue)
{
return leftValue.guidValue != rightValue.guidValue;
}
public static bool Equals(GuidToInt32 valueA, GuidToInt32 valueB)
{
return valueA.guidValue == valueB.guidValue;
}
public bool Equals(GuidToInt32 other)
{
return this.guidValue == other.guidValue;
}
public override bool Equals(object obj)
{
if (obj is GuidToInt32 color)
{
return GuidToInt32.Equals(this, color);
}
return false;
}
public override int GetHashCode()
{
return this.guidValue.GetHashCode();
}
}
这可以很容易地调整为与其他类型一起使用,例如uint
,long
,ulong
,float
,double
... >
我不会在绿色项目中使用它,但是它对于可恢复的迁移过程是完美的。