'c# .NET 4.8 How to create multi column index using default foreign keys on existing entity in DatabaseContext.cs
I'm using .NET 4.8. I have 3 tables: TableA, TableB and TableC. TableA has foreign key relationships already set up to TableB and TableC. This was done using a code first migration.
This is the code for TableA:
public class TableA : Entity<int>
{
public bool SomeColumn1 { get; set; }
public bool SomeColumn2 { get; set; }
public bool SomeColumn3 { get; set; }
public virtual TableB TableB { get; set; }
public virtual TableC TableC { get; set; }
}
So in my db TableA has the columns TableB_Id and TableC_Id that relate back to their respective tables.
I want to add a unique index to TableA such that the combination of TableB_Id and TableC_Id is unique.
I want to do this in my DatabaseContext.cs file using the FLUENT pattern. I added this to my DatabaseContext.cs in the OnModelCreating() method:
modelBuilder.Entity<TableA>().HasIndex(a => new { a.TableB, a.TableC }).IsUnique();
(a.TableB and a.TableC are the only options available when I enter a. )
I then compile my solution and try to create a migration but I get an error that says
Sequence contains no matching element
I found this SO post that suggests to add values in the base entity, so I changed my code for TableA to this:
public class TableA : Entity<int>
{
public bool SomeColumn1 { get; set; }
public bool SomeColumn2 { get; set; }
public bool SomeColumn3 { get; set; }
[Required]
[Index("IX_TableBAndTableC", 1, IsUnique = true)]
public int TableB_Id { get; set; }
public virtual TableB TableB { get; set; }
[Required]
public int TableC_Id { get; set; }
[Index("IX_TableBAndTableC", 2, IsUnique = true)]
public virtual TableC TableC { get; set; }
}
and TableB_Id and TableC_Id are now available in my code in DatabaseContext.cs but when I compile the solution and create a migration it drops the existing TableB_Id and TableC_Id columns on TableA and replaces them with TableB_Id1 and TableC_Id1 and then creates the index.
I then found this SO post that suggests to add a foreign key decorator to the base entity so I commented out the code in my DatabaseContext.cs file and changed my code in my TableA entity to be this:
public class TableA : Entity<int>
{
public bool SomeColumn1 { get; set; }
public bool SomeColumn2 { get; set; }
public bool SomeColumn3 { get; set; }
[ForeignKey("TableB_Id")]
public virtual TableB TableB { get; set; }
[ForeignKey("TableC_Id")]
public virtual TableC TableC { get; set; }
}
but when I compile the solution and generate a migration the migration is empty with nothing in the up() and down() methods.
I searched in the official documentation but was not able to find anything that specifically instructed on how to create a multi column unique index using the default columns that get created when I set up the foreign keys using a code first migration (TableA.TableB_Id and TableA.TableC_Id). The columns TableA.TableB_Id and TableA.TableC_Id are created by the entity framework automatically so I am not able to use them directly in my DatabaseContext.cs file.
Please can someone give me some help in figuring out how to create a multi column unique index on these two default foreign keys TableB_Id and TableC_Id by either adding something to the DatabaseContext.cs file or the base entity code for TableA, or both.
A correct, clearly explained answer will be marked as accepted and upvoted. Thanks.
Solution 1:[1]
After playing around with it I found this page that talks about foreign key relationships in entity framework. This is where I found a different way to format my code for my TableA entity that will accomplish what I need to do.
So here is the code for my TableA entity:
public class TableA : Entity<int>
{
public bool SomeColumn1 { get; set; }
public bool SomeColumn2 { get; set; }
public bool SomeColumn3 { get; set; }
[ForeignKey("TableB")]
public int TableB_Id { get; set; }
public virtual TableB TableB { get; set; }
[ForeignKey("TableC")]
public int TableC_Id { get; set; }
public virtual TableC TableC { get; set; }
}
This is very similar to one approach I tried in my original post, I just had a few things not set up right.
After I added this code to my TableA entity, back in my DatabaseCOntext.cs file I was able to add this line in the OnModelCreating() method:
modelBuilder.Entity<TableA>().HasIndex(a => new { a.TableB_Id, a.TableC_Id }).IsUnique();
which is now pointed at the fields TableA.TableB_Id and TableA.TableC_Id which weren't available before.
I compiled my solution and created a new migration and it appeared like it was going to do everything I needed it to.
I compiled the solution again and ran the migrations and the columns TableA.TableB_Id and TableA.TableC_Id are still present, set up as foreign keys to their respective tables and there is a unique constraint on them that will not allow duplicate rows to be inserted.
I hope this is helpful to others. If what I did is not clear, please leave a comment and I'll do my best to clarify.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Gharbad The Weak |
