I'm using Entity Framework 5.0 Code First;
public class Entity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string EntityId { get; set;}
public int FirstColumn { get; set;}
public int SecondColumn { get; set;}
}
I want to make the combination between FirstColumn
and SecondColumn
as unique.
Example:
Id FirstColumn SecondColumn
1 1 1 = OK
2 2 1 = OK
3 3 3 = OK
5 3 1 = THIS OK
4 3 3 = GRRRRR! HERE ERROR
Is there anyway to do that?
You need to define a composite key.
With data annotations it looks like this:
You can also do this with modelBuilder when overriding OnModelCreating by specifying:
If you're using Code-First, you can implement a custom extension HasUniqueIndexAnnotation
Then use it like so:
Which will result in this migration:
And eventually end up in database as:
I found three ways to solve the problem.
Unique indexes in EntityFramework Core:
First approach:
The second approach to create Unique Constraints with EF Core by using Alternate Keys.
Examples
One column:
Multiple columns:
EF 6 and below:
First approach:
This approach is very fast and useful but the main problem is that Entity Framework doesn't know anything about those changes!
Second approach:
I found it in this post but I did not tried by myself.
The problem of this approach is the following: It needs DbMigration so what do you do if you don't have it?
Third approach:
I think this is the best one but it requires some time to do it. I will just show you the idea behind it: In this link http://code.msdn.microsoft.com/CSASPNETUniqueConstraintInE-d357224a you can find the code for unique key data annotation:
The problem for this approach; How can I combine them? I have an idea to extend this Microsoft implementation for example:
Later in the IDatabaseInitializer as described in the Microsoft example you can combine the keys according to the given integer. One thing has to be noted though: If the unique property is of type string then you have to set the MaxLength.
I assume you always want
EntityId
to be the primary key, so replacing it by a composite key is not an option (if only because composite keys are far more complicated to work with and because it is not very sensible to have primary keys that also have meaning in the business logic).The least you should do is create a unique key on both fields in the database and specifically check for unique key violation exceptions when saving changes.
Additionally you could (should) check for unique values before saving changes. The best way to do that is by an
Any()
query, because it minimizes the amount of transferred data:Beware that this check alone is never enough. There is always some latency between the check and the actual commit, so you'll always need the unique constraint + exception handling.
The answer from niaher stating that to use the fluent API you need a custom extension may have been correct at the time of writing. You can now (EF core 2.1) use the fluent API as follows:
With Entity Framework 6.1, you can now do this:
The second parameter in the attribute is where you can specify the order of the columns in the index.
More information: MSDN