在构造函数中自动生成唯一ID

时间:2014-01-29 14:16:12

标签: vb.net constructor

使用VB.net,创建一个名为staff的新类,具有三个属性:     Name,LastName,ID - 应该适合用作数据库中的主键。

提供一个类构造函数来填充Name和LastName。 ID应该在构造函数中自动生成,不应该传入。

我知道如何创建类,属性和构造函数,我只需要知道如何在构造函数中自动生成ID字段。是否有可能做到这一点?

我通常做的是将数据库中的id字段作为标识字段和主键,以便自动插入下一个可用的id或在我的应用程序中,我从数据库中读取最后一个ID并添加一个。但我需要知道如何在构造函数中自动生成ID字段。

4 个答案:

答案 0 :(得分:6)

的Guid

如果您对ID类型没有任何约束,可以使用GUID:

Dim id As Guid = Guid.NewGuid()

您甚至可以将其保留为字符串:

Dim id As String = Guid.NewGuid().ToString("N")

应该授予它在不同机器上的唯一性(以满足您的要求,它必须适合用作数据库中的主键)。另请参阅this post

时间戳

情况更糟,如果您没有这样严格的要求(网络中的唯一性),您可以使用时间戳。当然,在这种情况下,您必须考虑更多问题:

  • 法定时间:每年时间往返两次。
  • 区域:如果用户在伦敦输入数据然后他移居纽约会怎么样?
  • 并发:您必须假设没有其他人向您的数据库添加记录(如果他们使用不同的技术,您可能会发生冲突)。如果执行是并发的(程序的多个实例一起运行),你也不能应用它。
  • 计时器粒度:系统日期具有粗粒度:如果您在短时间内构建了许多对象,那么您可能会有重复的ID。 this post
  • 中的解决方法

计数器

如果满足所有这些条件:

  • 您的应用程序的多个实例不会并行运行。
  • 您正在使用一台计算机(而非网络)。
  • 每次应用程序启动时数据库都为空。

每次构造新对象时,您都可以使用Shared计数器递增。如果系统计时器粒度不是问题(请参阅有关时间戳的段落),则可以使用system up time作为ID。由于有关粒度的限制,即使同时运行同一应用程序的多个实例,它也应该有效。

如果您使用Shared字段,则必须处理同步问题。根据{{​​3}}中的建议,您可以使用SyncLock。作为替代方案,您可以使用Interlocked.Increment操作。

哈希码

如果计数器的所有条件都满足,那么这个也是:

  • 您的申请是32位。
  • 您的对象不是ValueType,并且它不会覆盖GetHashCode()方法。

您可以使用哈希码(使用GetHashCode()获得),因为(来自this comment):

  

换句话说,ReferenceEquals方法返回true的两个对象具有相同的哈希码。

因为Object.ReferenceEquals()仅在比较同一个实例时返回true,所以每个实例都将具有唯一的哈希码(因为在32位应用程序哈希代码中是对象引用本身)。请注意,这是一个实现细节,可能会发生变化。

随机数

我知道这可能会让某人感到震惊,但64位值的好随机数生成器碰撞概率非常低。我重复极低概率(有关更多数学详细信息,请参阅MSDN)。只是不要使用System.Random

根据您使用的种子,您也可以在网络场景中生成随机数(不要忘记 - 需要引用 - 一个本地网络协议的早期草案提出了一个32位随机数作为地址,它已被由于用户反馈不好而改变了,但这并不意味着它无法正常工作)。

答案 1 :(得分:0)

你想要一个不会重复的数字!那么为什么不使用它?

    Dim dateAndTime As Date
    dateAndTime = Now
    TextBoxPID.Text = Format(dateAndTime, "yyyyMMddHHmmss").ToString

除非您的数据条目将在几毫秒内完成,否则此解决方案效果很好。如果您遇到毫秒问题,那么只需在字符串末尾添加一个计数器。

    counter +=1
    TextBoxPID.Text = Format(dateAndTime, "yyyyMMddHHmmss").ToString & counter.ToString

如果您正在使用网络并让多个人进行数据输入,请将其员工ID添加到字符串中。每个问题都有简单的解决方案,但在大多数情况下,如果不是所有情况,这都可以毫无问题地工作。

答案 2 :(得分:0)

根据SNTP服务器生成随机唯一用户ID。

我的要求有点不同;但我需要生成一个随机且唯一的用户ID,即10个数字,花费公平时间无法找到合适的解决方案。 所以我最终得到了以下功能;其独特而随机的结果。

根据一台测试机器上的一个应用程序瞬间,它是增量的唯一结果;因为用户将在非预选择时间戳上生成十位数字。除了使用随机alpha前缀;我希望这个功能可以提供解决方案:

Imports System.Globalization
Imports System.Net

Public Class GetNetTime
    Public Shared Function GetUTC()
        ' connect to google servers
        ' you could use some SNTP time servers but can't be sure port will be open
        ' or you could just ping your own webserver
        Dim myNetRequest As WebRequest = HttpWebRequest.Create("http://www.example.com")
        ' read response header from connection
        Dim response = myNetRequest.GetResponse()
        ' read date/time header
        ' assume its UTC format
        Dim GlobalUTC As String = response.Headers("date").ToString
        ' convert string to datetime object
        Dim parsedDateTime As DateTime = DateTime.Parse(GlobalUTC)
        ' get UNIX time stamp
        Dim unixTime = (parsedDateTime - New DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds
        Return unixTime 
    End Function
End Class

要测试输出,您可以添加:

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim utc As String = GetNetTime.GetUTC
        ' add random alpha prefix to UNIX time stamp
        Dim sPrefix As String = ""
        Dim rdm As New Random()
        For i As Integer = 1 To 3 ' if you need more than 3 alpah random charachters adjust i length
            sPrefix &= ChrW(rdm.Next(65, 90))
        Next
        MsgBox(sPrefix & utc) ' OR MsgBox("ID" & sPrefix & utc)
        ' code here to use result
    End Sub

我觉得这个解决方案比查询SQL表和读取最后一个记录id更有用,并且会增加。

备注

  • 请不要长时间回答;因为我试图评论代码和 详细解释这个场景。
  • 我觉得这对生成有好处 在多个工作站上运行的应用程序的UserID。
  • 请不要将此功能用于...循环或排气运行。

输出示例:

GYK1501270543

VWT1501270606

WRH1501270634

SKI1501270648

QXL1501270716

答案 3 :(得分:0)

这也基于上面的@wpcoder答案,但是是一种基本形式,这对我有用

    Public Function UIDGen(ByRef f As String) As String
        Dim currentTime As DateTime = DateTime.UtcNow
        Dim StringTime As String = currentTime.ToString
        Dim parsedDateTime As DateTime = DateTime.Parse(StringTime)
        Dim unixTime = (parsedDateTime - New DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds
        Dim utcString As String = unixTime.ToString
        Dim sPrefix As String = ""
        Dim rdm As New Random()

        For i As Integer = 1 To 3 ' 3 Letters enough ?
            sPrefix &= ChrW(rdm.Next(65, 90))
        Next
        f = (sPrefix & utcString)
        Return f
    End Function