在C#中生成序列号

发布于 2024-09-11 06:42:26 字数 204 浏览 7 评论 0原文

我正在使用 C# 开发 ASP.Net,我想生成一个如下所示的序列 id:

ELG0001 , ELG0002, ...

ELG 是前缀,0001 应该按顺序排列

我正在使用 sql server 2005

此 ID 将生成并添加到我的数据库中。我该怎么做?

你能帮我编码吗?

I am working on ASP.Net using C# I want to generate a sequence id that should be like this:

ELG0001 , ELG0002, ...

ELG is the PREFIX and 0001 should be in sequence

I am using sql server 2005

This ID will be generated and added to my database. How can I do this?

can you help me with coding?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

萌酱 2024-09-18 06:42:26

使用这段代码,我们可以简单地做到这一点,

public string CJ()
    {
        string Id = GenerateId("cust", "cust_id", 6, "ELG", true);
        return Id;
    }
    public string GenerateId(string TableName, string ColumnName, int ColumnLength, string Prefix, bool Padding)
    {
        string Query, con, Id;
        con = "Data Source=CJ\\SQLEXPRESS;Initial Catalog=seq;Persist Security Info=True;User ID=sa;Password=123";
        SqlConnection cn = new SqlConnection(con);
        int preLength,padLength;
        preLength = Convert.ToInt32(Prefix.Length);
        padLength = ColumnLength - preLength;
        if (Padding == true )
        {
             Query = "SELECT '" + Prefix + "' + REPLACE(STR(MAX(CAST(SUBSTRING(" + ColumnName + "," + Convert.ToString(preLength + 1) + "," + padLength + ") AS INTEGER))+1," + padLength + "),' ',0) FROM " + TableName;

        }
        else
        {
            Query = "SELECT '" + Prefix + "' + CAST(MAX(CAST(SUBSTRING(" + ColumnName + "," + Convert.ToString(preLength + 1) + "," + padLength + ") AS INTEGER))+1 AS VARCHAR) FROM " + TableName;
        }
        SqlCommand com = new SqlCommand(Query, cn);
        cn.Open();
        if (com.ExecuteScalar().ToString() == "")
        {
            Id = Prefix;
            if (Padding == true)
            {
                for (int i = 1; i  padLength - 1; i++)
                {
                    Id += "0";
                }
            }
            Id += "1";
        }
        else
        {
            Id = Convert.ToString(com.ExecuteScalar());
        }
        cn.Close();
        return Id;
}

感谢xx的帮助
只需添加方法 CJ()
正如我在这里所做的那样

protected void Button1_Click(object sender, EventArgs e)
    {
        string con;
        con = "Data Source=CJ\\SQLEXPRESS;Initial Catalog=seq;Persist Security Info=True;User ID=sa;Password=123";
        using (SqlConnection cn = new SqlConnection(con))
        {
            cn.Open();
            using(SqlTransaction trans = cn.BeginTransaction())
            using (SqlCommand cmd = cn.CreateCommand())
            {
                cmd.Transaction = trans;
                cmd.CommandText = "INSERT INTO cust([cust_id],[cust_name],[cust_add]) VALUES(@cust_id,@cust_name,@cust_add)";
                cmd.Parameters.Add("@cust_id",CJ());
                cmd.Parameters.Add("@cust_name",TextBox1.Text);
                cmd.Parameters.Add("@cust_add",TextBox2.Text);
                cmd.ExecuteNonQuery();
                trans.COmmit();
            }
            cn.Close();
            Response.Write("alert('DATA SAVED')");
            TextBox1.Text = "";
            TextBox2.Text = "";
        }

   }

using this code we can do it simply

public string CJ()
    {
        string Id = GenerateId("cust", "cust_id", 6, "ELG", true);
        return Id;
    }
    public string GenerateId(string TableName, string ColumnName, int ColumnLength, string Prefix, bool Padding)
    {
        string Query, con, Id;
        con = "Data Source=CJ\\SQLEXPRESS;Initial Catalog=seq;Persist Security Info=True;User ID=sa;Password=123";
        SqlConnection cn = new SqlConnection(con);
        int preLength,padLength;
        preLength = Convert.ToInt32(Prefix.Length);
        padLength = ColumnLength - preLength;
        if (Padding == true )
        {
             Query = "SELECT '" + Prefix + "' + REPLACE(STR(MAX(CAST(SUBSTRING(" + ColumnName + "," + Convert.ToString(preLength + 1) + "," + padLength + ") AS INTEGER))+1," + padLength + "),' ',0) FROM " + TableName;

        }
        else
        {
            Query = "SELECT '" + Prefix + "' + CAST(MAX(CAST(SUBSTRING(" + ColumnName + "," + Convert.ToString(preLength + 1) + "," + padLength + ") AS INTEGER))+1 AS VARCHAR) FROM " + TableName;
        }
        SqlCommand com = new SqlCommand(Query, cn);
        cn.Open();
        if (com.ExecuteScalar().ToString() == "")
        {
            Id = Prefix;
            if (Padding == true)
            {
                for (int i = 1; i  padLength - 1; i++)
                {
                    Id += "0";
                }
            }
            Id += "1";
        }
        else
        {
            Id = Convert.ToString(com.ExecuteScalar());
        }
        cn.Close();
        return Id;
}

thanxx for the help
just add the method CJ()
as i have done here

protected void Button1_Click(object sender, EventArgs e)
    {
        string con;
        con = "Data Source=CJ\\SQLEXPRESS;Initial Catalog=seq;Persist Security Info=True;User ID=sa;Password=123";
        using (SqlConnection cn = new SqlConnection(con))
        {
            cn.Open();
            using(SqlTransaction trans = cn.BeginTransaction())
            using (SqlCommand cmd = cn.CreateCommand())
            {
                cmd.Transaction = trans;
                cmd.CommandText = "INSERT INTO cust([cust_id],[cust_name],[cust_add]) VALUES(@cust_id,@cust_name,@cust_add)";
                cmd.Parameters.Add("@cust_id",CJ());
                cmd.Parameters.Add("@cust_name",TextBox1.Text);
                cmd.Parameters.Add("@cust_add",TextBox2.Text);
                cmd.ExecuteNonQuery();
                trans.COmmit();
            }
            cn.Close();
            Response.Write("alert('DATA SAVED')");
            TextBox1.Text = "";
            TextBox2.Text = "";
        }

   }
蓝梦月影 2024-09-18 06:42:26

下面是一个简单的 SQL Server ID 生成器:

CREATE TABLE IDSeed
(
    ID int IDENTITY(10001,1)
)
GO

CREATE PROCEDURE NewSequenceID
(
    @NewID char(7) out
)
AS
BEGIN
    INSERT INTO IDSeed DEFAULT VALUES

    SELECT @NewID = 'ELG' + RIGHT(CAST(SCOPE_IDENTITY() AS nvarchar(5)), 4)
END
GO

/*
 * Test the NewSequenceID proc
 */
DECLARE @TestID char(7)

EXEC NewSequenceID @TestID out

SELECT @TestID

IDSeed 表将继续累积行。这可能不是问题,但如果这是问题,您可以使用脚本定期清除表。剩下的唯一部分是从 C# 代码调用该过程并检索 @TestID 参数的值。

此示例基于您的问题:序列预计不会超过 9999 个元素。您必须修改代码才能支持更大的序列 ID。

请注意,过程 NewSequenceID 中不需要事务,因为 SCOPE_IDENTITY() 函数仅返回当前 SQL 会话中的值。如果另一个线程几乎同时执行插入,则 SCOPE_IDENTITY() 返回的值不会受到影响。

Here's a simple ID Generator for SQL Server:

CREATE TABLE IDSeed
(
    ID int IDENTITY(10001,1)
)
GO

CREATE PROCEDURE NewSequenceID
(
    @NewID char(7) out
)
AS
BEGIN
    INSERT INTO IDSeed DEFAULT VALUES

    SELECT @NewID = 'ELG' + RIGHT(CAST(SCOPE_IDENTITY() AS nvarchar(5)), 4)
END
GO

/*
 * Test the NewSequenceID proc
 */
DECLARE @TestID char(7)

EXEC NewSequenceID @TestID out

SELECT @TestID

The IDSeed table will continue to accumulate rows. This is probably not an issue, but if it is a problem you can purge the table with a script on a regular basis. The only part left is to call the procedure from C# code and retrieve the value of the @TestID parameter.

This example is based on your question: the sequence is not expected to exceed 9999 elements. You would have to modify the code to support larger sequence IDs.

Note that a transaction is not necessary in procedure NewSequenceID because the SCOPE_IDENTITY() function only returns values from the current SQL session. If another thread performs a near-simultaneous insert, the value returned from SCOPE_IDENTITY() won't be affected.

ぶ宁プ宁ぶ 2024-09-18 06:42:26

你几乎不能 - 最终你需要在持久数据存储(如 SQL Server)上生成数字,以保证唯一性,即使你的 ASP.NET 应用程序域的多个副本正在运行(这可能会定期发生)。

因此,数据库方面:

  • 您需要一个表来存储所有序列和最后分配的值(例如“ELG”“1” - 该数字可以存储数字)
  • 在事务中:读取最后一个数字,更新到下一个更高的数字,提交并返回格式化后编号为高代码级别。

You pretty much can not - you need to generate the numbers on and from a persistent data store (like SQL Server) ultimately, to guarantee uniqueness, even in case multiple copies of your ASP.NET appdomain are running (which may happen regularly).

So, database side:

  • You need a table for all squences and the last assigned value (Like "ELG" "1" - the number can be stored numeric)
  • IN a transaction: read last number, update to next higher one, commit and return number to high code level after formatting.
柠檬色的秋千 2024-09-18 06:42:26

我们使用的是 mssql 2005,我们面临着同样的问题,即具有带有前缀或后缀的唯一编号。

我们使用存储过程和表来为我们生成序列号

以下是存储过程的代码

CREATE PROCEDURE [get_next_receipt_no]
(
  @pSequenceValue INT OUTPUT
)
AS
BEGIN;
  BEGIN TRAN;
    INSERT INTO seq_receipt_no DEFAULT VALUES;
    SET @pSequenceValue = SCOPE_IDENTITY();
    DELETE FROM seq_receipt_no WHERE SEQ_ID <> @pSequenceValue;
  COMMIT TRAN;
END;

以下是表的代码

CREATE TABLE [seq_receipt_no](
    [SEQ_ID] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]

如果数据库是 oracle,您将获得作为可从 SQL 查询本身访问的对象的序列。 MSSQL没有这个功能。

We are using mssql 2005 and we were facing the same problem of having a unique number with a prefix or a postfix.

We used a stored procedure and a table to generate a sequence number for us

Following is the code for the stored procedure

CREATE PROCEDURE [get_next_receipt_no]
(
  @pSequenceValue INT OUTPUT
)
AS
BEGIN;
  BEGIN TRAN;
    INSERT INTO seq_receipt_no DEFAULT VALUES;
    SET @pSequenceValue = SCOPE_IDENTITY();
    DELETE FROM seq_receipt_no WHERE SEQ_ID <> @pSequenceValue;
  COMMIT TRAN;
END;

Following is the code for the table

CREATE TABLE [seq_receipt_no](
    [SEQ_ID] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]

If the database would have been oracle, you get sequences as objects accessible from SQL queries itself. MSSQL does not have this functionality.

沙与沫 2024-09-18 06:42:26

如果存在并发,第一个答案有时将不起作用。
其他解决方案以一张大表结束,但不需要它。

如果您使用的是 SQL Server 2016 或更高版本,则可以使用 SEQUENCE 对象,它是直接针对这种情况而设计的。查看 https://learn.microsoft.com/en-us/sql/t-sql/statements/create-sequence-transact-sql?view=sql-server-ver16

在以前的版本中,您可以使用正常的锁定机制来实现
您需要什么:

您将需要一个序列表,您可以生成所需数量的序列行,我的意思是十个或十几个,而不是数百个,否则您最终会遇到瓶颈。

CREATE TABLE SequenceTable
(
   k_val  varchar(5) not null,  --Here you can put the ELG string or whatever
   my_serial int not null,
   CONSTRAINT PK_SequenceTable UNIQUE PRIMARY KEY CLUSTERED
)
GO

--To keep it simple I will asume there is a first row with a key_val
--And a positive value in my_serial
--And I won't handle errors nor exceptions
CREATE PROC GetKey(
  @key_val varchar(5)
)
As
Begin transaction  --To keep locks until the proc ends

   --With the normal isolation level, the UPDATE will put an exclusive 
   --lock on the Row, no one else can read or write until the commit
   --With this UPDATE I'll set the new value
   UPDATE SequenceTable
      SET my_serial = my_serial +1
   WHERE k_val = @key_val

   --Here, as the lock is mine, I can read and return the new generated Value
   SELECT my_serial
   FROM SequenceTable
   WHERE k_val = @key_val

commit transaction  -- The Lock is released
GO

通过这种方式,您可以使用正常的 ACID 数据库行为。

The first answer sometimes won't work if there is concurrency.
The other solutions ends with a large table without needing it.

If you're working with SQL Server 2016 or above you can use the SEQUENCE object, it's stright forward and made for this situation. Look at https://learn.microsoft.com/en-us/sql/t-sql/statements/create-sequence-transact-sql?view=sql-server-ver16

In previous versions you can use the normal locking mechanism to achieve
what you need:

You will need a Table For Sequence(s), you can generate as many rows as sequences you need, I mean ten or a dozen, not hundreds or you'll end up with a bottleneck.

CREATE TABLE SequenceTable
(
   k_val  varchar(5) not null,  --Here you can put the ELG string or whatever
   my_serial int not null,
   CONSTRAINT PK_SequenceTable UNIQUE PRIMARY KEY CLUSTERED
)
GO

--To keep it simple I will asume there is a first row with a key_val
--And a positive value in my_serial
--And I won't handle errors nor exceptions
CREATE PROC GetKey(
  @key_val varchar(5)
)
As
Begin transaction  --To keep locks until the proc ends

   --With the normal isolation level, the UPDATE will put an exclusive 
   --lock on the Row, no one else can read or write until the commit
   --With this UPDATE I'll set the new value
   UPDATE SequenceTable
      SET my_serial = my_serial +1
   WHERE k_val = @key_val

   --Here, as the lock is mine, I can read and return the new generated Value
   SELECT my_serial
   FROM SequenceTable
   WHERE k_val = @key_val

commit transaction  -- The Lock is released
GO

In this way you can use the normal ACID database behavior for you.

谜兔 2024-09-18 06:42:26

像这样的事情怎么样?

public enum SequenceIds
{
    ELG0001 = 1,
    ELG0002
}

public void Something()
{
    var x = SequenceIds.ELG0002;
}

How about something like this?

public enum SequenceIds
{
    ELG0001 = 1,
    ELG0002
}

public void Something()
{
    var x = SequenceIds.ELG0002;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文