2012-01-01 141 views
3

我必须为数据库中记录的生成唯一号码标识符创建逻辑。 id,在数据库中生成是一个单独的列。唯一号码标识符生成

此时,当用户调用“创建记录”操作时,我保存新记录,获取其数据库ID,使用此ID生成记录号,然后将其放入编辑表单。 使用这种方式意味着所有的实体字段都应该为空来保存记录到数据库。

我不喜欢这种方式。我知道这应该是更好的方式。

是否有更好的做法来生成唯一的数字标识符?生成非唯一随机数的可能性是什么?

谢谢

+0

[我前一阵子也有类似的问题(http://stackoverflow.com/questions/4761668/entity-framework-set-identity-insert)但没有提出一个好的解决方案。就我而言,我们希望能够在填写表格时通过电话阅读ID。一些答案建议使用GUID,这将是唯一的,但不适合我的问题。 – Rup 2012-01-01 10:25:58

+0

Jeff Atwood在他的博客上有一篇关于GUID genrate的文章,你可以参考它。 http://www.codinghorror.com/blog/2005/10/equipping-our-ascii-armor.html – JKhuang 2012-01-01 10:25:49

回答

6

您正在使用的保存空白记录以获取ID的模式并不是一个好的模式。

标准方法和我推荐的方法是创建记录只是显示一个空表单(此时的ID通常为0)。用户填写表单并且数据仅在用户单击保存时才提交给数据库。该ID应该是一个IDENTITY列。

您的方法存在的一个问题是,如果用户没有填写表单,那么数据库中会有很多不完整的记录。当然,这使得处理数据验证和完整性变得更加困难。

另一种方法,如果你真的真的必须显示ID给用户,是有一个单独的表,包含一个“下一个记录ID”列的行。此列可以作为原子操作递增并返回,并用于填充新记录的ID。您仍然不创建真实记录,只需在“创建记录”操作中增加此“下一个记录ID”即可。使用这种方法,您可以在多个实体中使用相同的方法,方法是在此“记录ID”表中为每个实体分别设置不同的行。请记住,如果用户最终没有将记录保存到数据库,则ID仍然会被“用完”。这些数字仍然是独一无二的,将按时间顺序排列,但不一定是连续的。

+0

我尝试了第二种方法。这确实意味着第一个表上的ID列不能再是一个标识(因为AFAIK [EF不支持SET IDENTITY INSERT](http://stackoverflow.com/questions/4761668/entity-framework-set-identity-插入))但这并不是太多问题。 – Rup 2012-01-01 10:30:14

+0

但我该如何增加下一个记录ID而不将记录保存到数据库? – xwrs 2012-01-01 10:45:19

+0

@xwrs,下一个记录ID只是一个单独的表中的数值。更新包含下一个记录ID的行以便为您的实体派生ID不存在任何问题 - 但不要将实体插入* its *表格,直到用户在数据输入屏幕上点击“保存”为止。 – 2012-01-01 20:57:35

0

从.NET本身尝试Random类。

+0

问题是它需要对数据库中已有的任何东西都是唯一的,但对于其他所有可能的用户也是唯一的打开网页表单。你需要更多的东西,而不仅仅是一个随机数来保证这一点。 – Rup 2012-01-01 10:28:00

1

我不明白这一点,但是,如果你正在使用的数据库,即转化为Guid在C#中uniqueidentifier数据类型,所以你可以做:

public Guid CreateRecord(MyObject model) { 

    Guid newId = Guid.NewGuid(); 

    MyTable tbl = new MyTable(); 
    tbl.guid = newId; 

    // ... other columns 

    db.MyTable.AddObject(tbl); 
    db.SaveChanges(); 

    return newId; 
} 

虽然我通常做的,将PrimaryKey设置为int,并添加一个名为​​的uniqueidentifier字段(我公开使用它而不是column_id),并记住为该列编制索引。

+0

Guid不是一个数字,但在将其保存到数据库之前,我需要一个九位数的数字作为附加的记录标识。 – xwrs 2012-01-01 09:57:48

+0

Guid是一个随机数(当你使用'C#'和'SQL'中的'Guid.NewGuid();')时(当使用'uniqueidentifier'数据类型时)...为什么不使用它? – balexandre 2012-01-01 09:59:29

+0

@xwrs,盖下一个Guid是一个128位的数字 – kenny 2012-01-01 13:34:38

0

为记录生成唯一编号的想法是使用time()以毫秒为单位(因为参考时间点,例如01/01/2010)。

但是,如果有两个记录同时得到更新,这可能会导致问题。为了解决这个问题,如果每个用户都可以分配一个号码(当创建用户ID时),那个“用户号码”和时间(毫秒)的组合(连接)将给你你需要的唯一号码。

+0

其实我必须在将用户的ID保存到数据库之前向用户显示记录的ID。 – xwrs 2012-01-01 10:05:05

1

代码表..

CREATE TABLE TblTransactions(
    TId varchar(8), 
    TName varchar(50) 
) 

C#代码隐藏...

protected void Page_Load(object sender, EventArgs e) 
{ 
    string id = GenerateId("TblTransactions", "TId", 8, "TRN"); 
// insert the id along with data in the table 
    Response.Write(id); 
} 

public string GenerateId(string TableName, string ColumnName, int ColumnLength, string Prefix) 
{ 
    SqlConnection con = new SqlConnection("server=.;integrated security=true;database=EBissCard"); 
    string Query, Id; 
    int PrefixLength, PadLength; 
    PrefixLength = Convert.ToInt32(Prefix.Length); 
    PadLength = ColumnLength - PrefixLength; 
    Query = "SELECT '" + Prefix + "' + REPLACE(STR(MAX(CAST(SUBSTRING(" + ColumnName + "," + Convert.ToString(PrefixLength + 1) + "," + PadLength + ") AS INTEGER))+1," + PadLength + "),' ',0) FROM " + TableName; 

    SqlCommand com = new SqlCommand(Query, con); 
    con.Open(); 
    if (com.ExecuteScalar().ToString() == "") 
    { 
     Id = Prefix; 
     for (int i = 1; i <= PadLength - 1; i++) 
     { 
      Id += "0"; 
     } 
     Id += "1"; 
    } 
    else 
    { 
     Id = Convert.ToString(com.ExecuteScalar()); 
    } 
    con.Close(); 
    return Id; 
} 
+1

这是史蒂夫第二个想法的实现,使用一个简单的表来记录新发布的ID并将实际数据存储在不同的表中? – Rup 2012-06-18 15:48:29