Guarantee unique value in database - c#

I have a registration table in my database with a field RegistrationNumber which needs to be unique.
I am wondering about what is the best way to guarantee that I will provide unique number in every case.
What I do is in my Repository I save the new Registration, something like:
void IMyRepository.Repository(Registration registration)
{
registration.RegistrationNumber = _getNewRegistrationNumber();
dbContext.SaveChanges();
}
private string _getNewRegistrationNumber()
{
// what to do? get last registration number and increment? it could be
// either integers or integers mixed with letters.
}
What I'm worried about is if two people complete the registration form at the same time, I'm afraid that before the first one arrives at dbContext.SaveChanges(); the second one will enter the _getNewRegistrationNumber() function and might get the same RegistrationNumber.
Any advise?
[EDIT]
: GUID is too long

You have 3 options:
Use an computed Identiy column (Auto Increment) that will automaticly be created, if you insert a new record. The drawback is, you need a rountrip to the database, before you have an Number
Use a Guid
Use a unqiue index in your database and compute your own number. If the number already exist on save, you can catch a Exception.

The best way to guarant unique value is GUID:
void IMyRepository.Repository(Registration registration)
{
registration.RegistrationNumber = Guid.NewGuid().ToString();
dbContext.SaveChanges();
}

Related

Create random string and check its uniqueness in DB

Check the code bellow, the RandomMan.MyRandomString(64) is generating a random string of 64 char.
Now I want to check if this random string is unique in database using entityframework query like bellow. And if this string is not unique in database then it will continue the do loop until it finds a unique random string. Now my question is am I doing it correctly? Or is there any better way than that?
string randstr;
do {
randstr = RandomMan.MyRandomString(64);
} while (DataCtx.StorageFiles.Any(x => x.AwsUniqueFileName == randstr));
I cannot tell whether or not you are doing it correctly, but if you already have the row in DB, I could suggest concatenating (adding) your identity field id to the produced string so you make sure that the result is unique in the DB, given that your MyRandomString only produces chars (or no numbers at the end)
Let's say your generated string is abc and the id of the row you are updating is 53 then your final unique string is going to be abc53
Standard approach for this is to just generate GUID:
Console.WriteLine(Guid.NewGuid());
It's designed to be unique and highly unlikely to generate two identical GUIDs even on many instances at the same time so you don't need to worry much about atomicity of this operation.
The possibility of collision is so low that you can skip handling it at all, but just to be sure you can set unique key on this column and treat it as an exception, no need for loop for sure.

How to calculate the (custom id) for a row which has not been inserted yet?

I am using the answer of this question How to automatically generate unique id in sql server to create a custom id for a table.It worked perfectly.Now I have a column which holds the values such as UID00000001 UID00000002 and so on. Suppose the last value in this column is UID00000003.Now I want to calculate the value for the row which hasn't been inserted yet via C# in one of my .aspx pages.In this case UID00000004. How can I achieve this value?
Any help would be appreciated.
Thank you.
If you are not required to generate these identifier at database level (e.g. some other processes insert records there), you can pre-generate them within your application. Something like above:
class Generator
{
public static int UniqueId = 0;
public static int GetNextId()
{
return Interlocked.Increment(ref UniqueId);
}
}
Then, your code can preallocate these identifiers and also format those strings. If multiple users access the same functionality, they will receive other identifiers. However, if one does not (successfully) performs a save operation, those identifiers will be lost.
You need to execute this query to get the next identity which will be generated for the table:
SELECT IDENT_CURRENT('table_name')+1;
For your case, it will have some other info concatenated with the next identity so the query will be like this:
SELECT 'UID' + RIGHT('00000000' + CAST(IDENT_CURRENT('table_name')+1 AS VARCHAR(8)), 8)
Of course you will need to write the C# code to send that query to the SQL Server.
Having said that, keep this in mind: When you get the value from that call and hold onto it, if during the time you are holding the value a record is inserted into that table, then the value is no longer the next value.
If you need the identiy value after a record is inserted in your application, please refer this answer.

How to implement Identity for group of records?

I have a table that contains a non primary key RequestID. When I do a bulkInsert, all the records must have the same RequestID. But If I do another BulkInsert, the next inserted rows must have RequestID incremented :
NewRequestID = PreviousRequestID + 1
The only solution I found so far -and I don't like it by the way-, is to get the last record everytime before inserting the new records.
Why I dont like this approach ? because the database is supposed to be relationnel, which means there is "no specific order". Besides, I don't have primary keys or Dates to order with.
What is the best way to implement this?
(I've added c# tag because i am using EF. if there is an easy solution with EF)
You could take a number of different approaches:
Are you guaranteed that your RequestID's are always incremented? If so, you could query table for largest RequestID and that should represent the "last one inserted."
You could track state somewhere in your application, but this is likely dangerous in scenarios where service fails/restarts (unless state is tracked externally).
Assuming you have control over the schema, if you don't want to update the particular table schema you are speaking of, you could create another table to track the last RequestID used, and retrieve it from there (which would protect you against service restarts/failures).
Those are a few that come to mind.
UPDATE:
Assuming RequestID isn't a particular type of identifier, you could use timestamp - which will always be incremented when you do a new batch, however, I'm not sure if you needed it to always be incremented by exactly '1' which would preclude this approach.

Entity Framework ensure objects get inserted in order

I have a table Rules on my database. I insert rules like:
Rule[] rulesToInsert = // some array of rules to insert
using(var db = new MyEntities())
{
foreach(var rule in rulesToInsert)
db.Rules.Add(rule);
db.SaveChanges();
}
When I retrieve later the rules that I have just added I notice they are in a different order. What is the best way to retrieve them in the order I added them? Should I call db.SaveChanges() every time I add a new rule? Or should I add a new column called SortOrder? Why are the items not being added in the order I added them?
Edit
The id is a guid (string) because one rule can have other rules. In other words I am creating a tree structure. (The rules table has a foreign key to itself). It was crashing when I used the primary key as an integer and it autoincremented so I just used a guid instead. I guess I will add a separate column called sort order.
Tables have no sort order (new rows are not guaranteed to be added to the end or any other place). The only safe way to retrieve rows in any particular order is to have a query with Order by.
So yes you will need to add a SortOrder column. (Can just set it as an identity column.)
If you want your items to be inserted in the order you add them in the foreach statement, you have to make a big compromise, to call the db.SaveChanges in each iteration.
foreach(var rule in rulesToInsert)
{
db.Rules.Add(rule);
db.SaveChanges();
}
I say that's a big compromise, because for each rule you have to insert you have to make a round-trip to the database, instead of doing only one round-trip as in your original code.
One possible workaround, it would be to add an extra column in the corresponding table in your database, that would hold the information of order. If you do so, you could add one more property in the rule object and refactor a bit your code. Then you will have the expected result.

How can I get the current username - USING MY CODE BELOW IN ASP.NET

How can I get the current username of whoever made changes on a table? A button?
private string GetCurrentUserName()
{
return Utilities.CurrentUsername();
}
UTILITIES:
public static string CurrentUsername()
{
string[] data = HttpContext.Current.User.Identity.Name.ToString().Split(new char[] { '\\' });
string retVal = data[1];
return retVal;
}
If you are referring to changes on a database table, you will need to track the user who last updated each record in the table itself. I typically use an update_user and update_dt column in every table for his purpose. I make sure every update, insert, and delete update this columns with the user and date/time of the update. You can also have a pair of create_user and create_dt columns to maintain row creation.
I think you need to clarify what you mean in your question however. Getting the last update user of a button doesn't make any sense, unless you store each time the button is clicked somewhere.

Categories

Resources