0

我有我的asp.net MVC Web應用程序內的庫法,自動生成一個唯一的序列號被稱爲標籤: -替代使用MAX + 1創建一個用戶友好的唯一的序列號

public void InsertOrUpdateServer(TMSServer server, string username) 
     { 

    if (server.TMSServerID == default(int)) 
      { 
       // New entity 
    int technologyypeID = GetTechnologyTypeID("Server"); 
    Technology technology = new Technology 
     { 
    IsDeleted = true, 
    Tag = "S" + GetTagMaximumeNumber(technologyypeID).ToString(), 
    StartDate = DateTime.Now, 
    }; 
    Save(); 
//code goes here 

在哪裏在GetTagMaximumeNumber()函數是: -

public int GetTagMaximumeNumber(int typeID) { 
string s = tms.Technologies.Where(a => a.TypeID == typeID).Max(a2 => a2.Tag.Substring(1)); 

      if (s != null) 
      { 
      return Int32.Parse(s) + 1; 

      } 
      else { 
       return 100;//if this is the first record created 
      }} 

以上將獲得標籤的最大數加1,然後嘗試將其保存到數據庫中。上述方法運行良好,但我確信在生產服務器上多個用戶將添加記錄時,將生成相同的標記號,並在嘗試添加數據庫中已存在的自動生成的標記號時引發異常。 所以,我有以下問題:-1

  1. 什麼是我可以跟着有一個序列號,始終是唯一的其他方法。

  2. 在我目前的方法中,標籤號碼中的空白是最小的。只有當用戶刪除記錄並且其標籤號不是最大值時纔會出現間隙。那麼有沒有辦法在任何新方法中仍然有這種方法,所以差距會很小?

感謝您的幫助。

+1

可以使用['AUTO_INCREMENT'](http://www.w3schools.com/sql/sql_autoincrement.asp) – amdixon

+0

當然,如果刪除了一行,它* *是最大值,那麼你最終(在兩個不同的時間點)與兩個具有*相同*標記的實體。這可能是也可能不是問題,但值得記住。 –

+0

@amdixon自動增量在我的情況下不起作用,因爲我的標籤編號以字符串爲前綴。所以我可能有兩個具有相同整數的標籤,但是它們的第一個字符串如S100和R100不同。所以我沒有使用auto_increment出於這個原因。 –

回答

1

這個問題的完整解決方案是將自動遞增列和計算列結合使用。

表會是這個樣子:

CREATE TABLE [dbo].[somedata](
    [id] [bigint] IDENTITY(1,1) NOT NULL, 
    [reference] [varchar](50) NULL, 
    [STag] AS ('S'+CONVERT([varchar](19),[id],(0))), 
    CONSTRAINT [PK_somedata] PRIMARY KEY CLUSTERED ([id] ASC) 
) 

隨着映射:

public class SomeDataMap : EntityTypeConfiguration<SomeData> 
{ 
    public SomeDataMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.id); 

     // Properties 
     this.Property(t => t.id) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

     this.Property(t => t.reference) 
      .HasMaxLength(50); 

     this.Property(t => t.STag) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); 
    } 
} 
+0

感謝您的回覆,但這不會在我的工作案例,正如我前面提到的,一些標籤將以「S」開頭,其他以「SO」等開頭,依賴於techType –

+0

@JohnJohn,您可以改變規則以使用基於其他值的不同前綴。只是試圖想出一些可以節省額外閱讀或通過數據庫拖網的東西。 – qujck

1

如果在SQL 2012的新序列是不是一種選擇(因爲你不能升級),你可以創建一個存儲最後序列號的表格。

在EF背景下,代表類會是什麼樣子

class TaggedSequence 
{ 
    [Key] 
    public int Id { get; set; } 

    [Required] 
    public int Last { get; set; } 

    [Required] 
    [Column(TypeName = "CHAR"), StringLength(1)] 
    public string Tag { get; set; } 

    [Timestamp] 
    public byte[] Rowversion { get; set; } 
} 

而且準系統程序使用它:

using (var context = new MyContext()) 
{ 
    try 
    { 
     var tag = "S"; 
     var sequence = context.TaggedSequence.Single(s => s.Tag == tag); 
     sequence.Last += 1; 
     Technology technology = new Technology { ... }; 
     technology.Id = tag + sequence.Last; 
     context.Technologies.Add(technology); 
     context.SaveChanges(); 
    } 
    catch (DbUpdateConcurrencyException ex) 
    { 
     // Retry 
    } 
} 

(你必須在適應它到您的存儲庫對象)

併發檢查是爲了防止併發用戶繪製相同的數字。 Rowversion確保只有在獲取記錄和更新記錄之間其值不變時才允許更新。

+0

所以你是否意味着我應該預先使用序列號填充TaggedSequence表? –

+0

是的,你是對的。忘了提到這一點。這將是一次性操作。 –

+0

但我從來沒有遇到這樣的實施,你是否覺得這樣做是正確的? –