Get Identity Attribute value before inserting in Database - c#

I have a table and it has one of the attribute set as identity. I want to get the value of the identity attribute that would be generated after I enter a value to the database.
I have EmpTable made of EmpID and EmpName. EmpID is set as Identity. I want to fetch the EmpID value before inserting a new row to the database.

I would advise against trying to do this with a table that is set up to use an integer column as the primary key. You will run into concurrency problems if you simply fetch the previous ID and increment it. Instead you should use a GUID (uniqueidentifier in SQL) as your primary key.
This will allow you to generate a new GUID in your code that can safely be saved to the database at a later stage.
http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx
http://msdn.microsoft.com/en-us/library/ms187942.aspx

Sure the server knows where the auto-increment count is in its sequence, but there is almost nothing useful you can do with that information. Imagine you go to the Post Office and they hand out numbered tickets so they can serve customers in order. Of course you could ask them what the next number they'll give out is, but since anyone can walk in at any time you don't know you'll get that number. If you don't know that you'll get it, you can't do anything with it - e.g. writing it as a reference number on a form would be a mistake.
Depending on what you're trying to do, your two main options are:
Use a client-generated guid as your identifier. This kind of messes up the order so the analogy isn't great, but imagine if each customer who walked in could generate a random number that they are sure would never have been used before. They could use that to fill out forms before taking a number.
Take a number, but do it in a transaction with the other operations. A customer can take a number and use it to fill out some paperwork. If they realize they left their money at home, they just throw everything away and you never call their number.
Why do you think you need this information? Can you use either of these strategies instead?

Related

Redirect queries from one entity to another using c# / entity framework

This is a bit of a puzzle I'm trying to figure out.
I am working on a system where we have a number of company records saved in the database. Some of these records are duplicates and are no longer wanted/required.
However, several external systems are still mapping to these invalid records. If we were to delete them entirely it would cause errors to the systems still wanting to get the detail of that company.
The ideal workflow I would like would be;
The external system looks up Company ID X.
The current system has a table which has a record of all the remapped records, so when the request comes in, the table specifies to redirect Company ID X to Company ID Y.
There are a number of endpoints that could be altered one-by-one to do this - but it would be time-consuming, resulting in lots of repetition too.
My question is, using Entity Framework and .Net - is there a smart way of achieving this workflow?
My initial thoughts were to do something with the constructor for the company object, which repopulates the object from EF if a 'redirect' exists, but I don't know if this will play nice with navigation properties.
Would anyone have an idea?
Thanks very much.
You can create a column with foreign key for the same table to express the single unique valid company.
For example, you can add DuplicateOf column:
ALTER TABLE [Company]
ADD COLUMN [DuplicateOf] bigint NULL,
FOREIGN KEY [DuplicateOf] REFERENCES [Company] ([Id]);
and express this relation in your code:
public class Company
{
// ...
public Company DuplicateOf { get; set; }
// May be useful, hides check for duplicate logic:
public bool IsDuplicate => DuplicateOf != null;
// May be useful as well,
// returns the non-duplicate uniue company, not a duplicate, either linked or current:
public Company EffectiveCompany => DuplicateOf ?? this;
}
You will have to address EffectiveCompany when you want to work with non-duplicate and maintain this column to always point to the correct record. It will also result into additional query, if eager-loaded.
Another idea is to have a stored procedure GetCompany(bigint id) which will return the effective record - if DuplicateOf exists, or record itself otherwise. It will be good for your external systems and will let you hide all this stuff behind abstraction layer of stored procedure. If you decide to change it in future, then you can easily update it without breaking external systems.
However, for you it isn't always convenient to work with stored procedures with EF.
These are just ideas and not the best solutions, anyway.
In my opinion, the best solution would be to get rid of duplicates, update data everywhere and forget forever about this mess of duplicated data.

Generate Invoice Number for Multi user environment in C#

I am generating invoice numbers using Max function and adding 1 to the last invoice number. Very straightforward. but i applied this into Multi User environment getting problem. because two users open a invoice window at a same time both could get same id, invoice number should be the first thing to appear and not the last so i cannot use identity (auto generate id) for invoice number. I want to generate invoice number for Multi User environment windows form application in C#...
The other problem is what will happen two users accessing and updating the same record same time.
I hope you will understand the problem. i read about the Optimistic vs. Pessimistic locking but i need a solution. so can anyone please reply to me
Have a different database table that will store the max invoice number.
When a user opens the invoice window, run a stored procedure to:
Lock the table
Get the current number
Store the current+1 number
Unlock the table
Return the current+1 number
This will ensure that even though there are simultaneous requests you will always get a unique invoice number.
The flip side:
1. This stored procedure cannot run simultaneously for multiple users so it would be a bottleneck in case of high traffic.
2. There will be holes in the invoice numbers - holes where the invoices are cancelled.
If you are not positive with this approach then the invoice number must be generated at the time of saving and it would be an IDENTITY column but you have mentioned that users would like to see the invoice number when they start working on the invoice.
Update:
I found an excellent article that elaborates the above approach using sp_getapplock. The article link is HERE. I would recommend to use this approach.
Generally the problem is your application makes bad requirements and the approach is not suitable.
The invoice number should not be allocated when the invoice is created for editing, but when it is put into the system for transaction. This way an abort does not leave gaps.
Collect the invoice details, then create the insert via a stored procedure that puts the proper locks in place. This is trivial - if you know how to put either a lock on the relevant table, or use an applock for this SP.
Generally this is one of the few places a stored procedure makes sense. Generates a non-accounted for invoice with 0 line items so your application then can add the details. Voila, problems solved. If the user aborts, mark the invoice as "cancelled" and finished.
The auto increment column is the best solution. this is what we call Identity column in SQL Server.
If in your case you are not able to use it you could make a thread safe method in your server side code to generate the invoice id based on a static attribute.
Make sure that you are using a service in a single instance mode.
static long invoiceId = getMaxFunction();
...
...
public long GenerateInvoiceId()
{
lock(this)
{
return invoiceId++;
}
}

Concurrency issue

We are creating a client server application using WPF/C# with SQL. Here we are generating a unique number b checking DB(To get the last maximum number) and with that max value, we are increment '1' and storing the value in DB. At this time another user also working on the same screen and creating unique numbers, in some case the the unique numbers gets duplicated and throws exception.
We found this is a concurrency issue.
Indeed, fetching a number out, adding one, and hoping it still isn't in use is a thread-race and a race between multiple clients - and should be avoided.
Options:
use an IDENTITY column in the database, and let the database generate the value itself during INSERT; the database server knows how to do this safely and reliably
if that isn't possible, you might want to delay this code until you are ready to INSERT so it is all part of a single database operation - and even then, if it isn't in a "serializable transaction" (with key-range read locks, etc), then you would have to loop on "get the max, increment, try to insert but note that we might have lost a race, so only insert if the value doesn't exist - which it might; repeat from start if unsuccessful"
alternatively, you could create the new record when you first need the number (even though the rest of the data isn't available), noting that you might still need the "loop until successful" approach
Frankly, the IDENTITY column approach is the simplest.
Finally, We have follwed Singleton pattern with lock to resolver this issue.
Thanks.

UserID number not in order after deleting a user

I have a table called tblUserLogin. One of the columns is labeled UserID. Evertime I add a user it numbers them in order (ex. 1, 2, 3). If I delete numbers 2 & 3 and then add another user the user has a UserID of 4, the next number in line. Should it be number 2? Is this a setting in the properties window that needs adjusted? Thanks
No, it absolutely should not be 2. It's presumably meant to be a unique identifier. If some other system still knows about user ID 2, then when it asks your system for user 2 you should be able to say that the user doesn't exist - not give back information about the wrong user.
Reusing identifiers would be a really bad idea, basically. Once an identifier has been allocated to an entity, there should be no way of the same identifier (in the same context) referring to a different entity, nor should there be any way of changing the identifier used for that entity.
You've not stated which database type you're using, however:
The UserID column is probably an identity column. This means it will take the next value, that has never been used (subject seed and increment settings if you're in sql server).
You can't get this to take unused values without taking on the job of generating these identities yourself.
Assuming you're using a SQL Server IDENTITY column, then that's the correct and expected behaviour. However, if you'd like to reuse the deleted IDs from the gaps, take a look at Example B from SQL Server Books Online: Using generic syntax for finding gaps in identity values

Defining Status of data via Enum or a relation table

I have an application which has rows of data in a relation database the table needs a status which will always be either
Not Submitted, Awaiting Approval, Approved, Rejected
Now since these will never change I was trying to decide the best way to implement them I can either think of a Status enum with the values and an int assigned where the int is placed into the status column on the table row.
Or a status table that linked to the table and the user select one of these as the current status.
I can't decide which is the better option as I currently have a enum in place with these values for the approval pages to populate the dropdown etc and setup the sql (as it currently using to bool Approved and submitted for approval but this is dirty for various reasons and needs changed).
Wondering what your thought on this were and whether I should go for one or the other.
If it makes any difference I am using Entity framework.
I would go with the Enum if it never changes since this will be more performant (no join to get the status). Also, it's the simpler solution :).
Now since these will never change...
You can count on this assumption being false, and sooner than you think.
I would use a lookup table. It's far easier to add or change values in a lookup table than to change the definition of an enum.
You can use a natural primary key in the lookup table so you don't need to do a join to get the value. Yes a string takes a bit more space than an integer id, but if your goal is to avoid the join this will accomplish that goal.
I use Enums and use the [Description("asdf")] attribute to bind meaningful sentences or other things that aren't allowed in Enums. Then use the Enum text itself as a value in drop downs and the Description as the visible text.

Categories