Ef Core 3.1按属性生成主键

时间:2020-07-13 14:57:42

标签: c# entity-framework asp.net-core

如何通过对象的属性生成主键? 我需要像哈希这样的东西。但是稳定的哈希值;

public Object1 {
   public Object1(string property1, DateTime property2)
   {
      Property1 = property1;
      Property2 = property2;
      StableHashID = GetStableHash();
   }
   
   [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
   public int StableHashID { get; private set; } 

   public string Property1 { get; private set; }

   public DateTime Property2 { get; private set; }

   public int GetStableHash()
   {
      return ...; // ???
   }

}

4 个答案:

答案 0 :(得分:1)

导游足以满足您的需求。如果您仅将ID列用作索引,Guid.NewGuid()将为您生成一个很好的哈希值。

Guid.NewGuid() makes an actual guid with a unique value, what you probably want.

Guid.NewGuid() vs. new Guid()

但是,如果在哈希解密后找到对象值,则可以进行检查;

Encrypting & Decrypting a String in C#

答案 1 :(得分:1)

没有反思:

   public int GetStableHash()
   {
      var now = DateTime.Now;
      var nowInt = (int) now.Kind;
      var nowTicks = (ulong) now.Ticks;
      return (((ulong) nowInt) << 62) | nowTicks;
   }

具有属性:https://stackoverflow.com/a/12393880

编辑:

但是我仍然认为GUID足够好-自动生成的,增量的,具有EFCore的优点(例如Update方法)等。

Fluent API:

public override void Configure(EntityTypeBuilder<Entity> entityBuilder)
{
      entityBuilder.Property(entity => entity.Id).HasDefaultValueSql("NEWID()");   
}

或带有注释:[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

答案 2 :(得分:1)

您要基于其他属性值生成主键,然后需要在GetStableHash方法中从这两个属性值生成不同的哈希值。

  public class Object1
    {
        public Object1(string property1, DateTime property2)
        {
            Property1 = property1;
            Property2 = property2;
            StableHashID = GetStableHash();
        }

        [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int StableHashID { get; private set; }

        public string Property1 { get; private set; }

        public DateTime Property2 { get; private set; }

        public int GetStableHash()
        {
            var result = default(byte[]);

            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream, Encoding.UTF8, true))
                {
                    writer.Write(Property2.Ticks);
                    writer.Write(Property1);
                    writer.Write(Guid.NewGuid().ToString());
                }

                stream.Position = 0;

                using (var hash = SHA256.Create())
                {
                    result = hash.ComputeHash(stream);
                }
            } 

            return BitConverter.ToInt32(result, 0); 
        }

答案 3 :(得分:-1)

我找到了另一个解决方案。

 public override int GetStableHash()
        {
            int result = GetDeterministicHashCode(ErrorCode.ToString());
            result = (result * 397) ^ (GetDeterministicHashCode(Property1.ToString()));
            result = (result * 397) ^ (GetDeterministicHashCode(Property2.ToString()));
            return result;
        }

// https://stackoverflow.com/questions/5154970/how-do-i-create-a-hashcode-in-net-c-for-a-string-that-is-safe-to-store-in-a
        private int GetDeterministicHashCode(string str)
        {
            unchecked
            {
                int hash1 = (5381 << 16) + 5381;
                int hash2 = hash1;

                for (int i = 0; i < str.Length; i += 2)
                {
                    hash1 = ((hash1 << 5) + hash1) ^ str[i];
                    if (i == str.Length - 1)
                        break;
                    hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
                }
                return hash1 + (hash2 * 1566083941);
            }
        }
相关问题