Entity Framework 6.1 - Create index with INCLUDE statement
Strictly speaking it has been always possible in Code First Migrations because you can run sql in a migration:
public partial class AddIndexes : DbMigration
{
private const string IndexName = "IX_LogSamples";
public override void Up()
{
Sql(String.Format(@"CREATE NONCLUSTERED INDEX [{0}]
ON [dbo].[Logs] ([SampleId],[Date])
INCLUDE ([Value])", IndexName));
}
public override void Down()
{
DropIndex("dbo.Logs", IndexName);
}
}
But I realise that you are probably actually asking if you can create an index using the IndexAttribute introduced in 6.1, but with an Include column - the answer to that is "No"
In Entity Framework 6.1 (not Core), how can I use the IndexAttribute to define a clustered index?
There can only be one clustered index on a table and by default Entity Framework/Sql Server puts it on the primary key.
So what use is the IsClustered
attribute on an index that is not the primary key? Good question! (+1)
This class:
public class Blog
{
[Key()]
public int Id { get; set; }
[MaxLength(256)]//Need to limit size of column for clustered indexes
public string Title { get; set; }
[Index("IdAndRating", IsClustered = true)]
public int Rating { get; set; }
}
will generate this migration:
public override void Up()
{
CreateTable(
"dbo.Blogs",
c => new
{
Id = c.Int(nullable: false, identity: true),
Title = c.String(maxLength: 256),
Rating = c.Int(nullable: false),
});
.PrimaryKey(t => t.Id)
.Index(t => t.Rating, clustered: true, name: "IdAndRating");
}
Alter the migration to this:
public override void Up()
{
CreateTable(
"dbo.Blogs",
c => new
{
Id = c.Int(nullable: false, identity: true),
Title = c.String(maxLength: 256),
Rating = c.Int(nullable: false),
});
CreateIndex("dbo.Blogs",
new[] { "Rating", "Title" },
clustered: true,
name: "IdAndRating");
}
And that should create your table without a primary key but with the clustered index on the other columns
EDIT
In your scenario where you don't need to insert, update or delete data, you don't need a full blown entity, you could use raw sql queries to populate the classes. You would need to add your own sql to the migration to create the table because EF won't automate it, but that means you can create the table and index just as you want it.
How to create index in Entity Framework 6.2 with fluent configuration
Well 26.10.2017 Entity Framework 6.2 was officially released.
It includes a possibility to define indexes with ease via Fluent API. Ho it is to use was already announced in the beta of 6.2.
Now you can use the HasIndex()
method, followed by IsUnique()
if it should be an unique index.
Just a small comparison (before/after) example:
// before
modelBuilder.Entity<Person>()
.Property(e => e.Name)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(new IndexAttribute { IsUnique = true }));
// after
modelBuilder.Entity<Person>()
.HasIndex(p => p.Name)
.IsUnique();
// multi column index
modelBuilder.Entity<Person>()
.HasIndex(p => new { p.Name, p.Firstname })
.IsUnique();
It is also possible to mark the index as clustered with .IsClustered()
.
EDIT #1
Added an example for multi column index and additional information how to mark an index as clustered.
EDIT #2
As additional information, in EF Core 2.1 it is exactly the same like in EF 6.2 now.
Here is the MS Doc artcile as reference.
Creating Unique Index with Entity Framework 6.1 fluent API
NOTE: Relevant to EF 6
You can use IndexAttribute
as mentioned but with Fluent API
instead of DataAnnotations
which will do the trick:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.HasColumnAnnotation(
"Index",
new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));
Unfortunately there is no other way to create unique indexes using Fluent API
. There is an open issue regarding this feature: Unique Constraints (Unique Indexes)
UPDATE: Entity Framework Core
In the latest EF Core release you can rely on
Fluent API
to specify indexes without additional tricks. HasIndex
allows to define it:modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name);
Hence it returs IndexBuilder
object you can use it for further index configurations (i.e uniqueness):
modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name)
.IsUnique();
How to create spatial index using EF 6.1 fluent API
Short answer- No, it is not. I have seen this tangentially referenced throughout blogs and have found no concrete examples of implementation. It seems to be related to the fact that spatial indexes are filtered indexes, which are not supported in Entity Framework.
As support for my answer I constructed a POC console app with the most recent version of Entity Framework (6.1). I took the following steps
- Created a model that had a property of the type DbGeography
- Enabled automatic migrations
Ran Update-Database -verbose insuring migration with the addition of an index was run. The index used the following:
modelBuilder.Entity<LocationEntity>().Property(t => t.Coordinates).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("ix_locationentity_coordinates")));
No indexes were created, but neither did the app crash. I could try permutations on this, but my example seems to follow the convention of entity framework: Official Fluent Documentation
Entity Framework Filter Index
In EF 6.1, the working way to make the this work with Code First and DbMigrations is to use the Sql
method in the DbMigration
class:
public partial class AddIndexes : DbMigration
{
public override void Up()
{
Sql(@"CREATE UNIQUE NONCLUSTERED INDEX
[IX_DefaultLanguageApplicationId] ON [dbo].[Languages]
(
[IsDefaultLanguage] ASC,
[ApplicationId] ASC
)
WHERE ([IsDefaultLanguage]=(1))");
}
public override void Down()
{
DropIndex("dbo.Languages", "IX_DefaultLanguageApplicationId");
}
}
But I realise that you are probably asking if you can create an index using the IndexAttribute introduced in 6.1, but with an Filter - the answer to that is "No"
Almost a duplicate of: Entity Framework 6.1 - Create index with INCLUDE statement
Related Topics
How to Use Left & Right Functions in SQL to Get Last 3 Characters
Why Is My SQL Server Order by Slow Despite the Ordered Column Being Indexed
How to Extract Certain Nth Character from a String in Sql
Presto Check If Null and Return Default (Nvl Analog)
Sql Server Left Join with 'Or' Operator
Convert a Binary Stored as Varchar to Binary
Geometry and Geography Difference SQL Server 2008
How to Update a Varbinary Field with a Specific Value
Duplicating Records to Fill Gap Between Dates
Sql Server - Return Schema for Sysobjects
Pure-SQL Technique for Auto-Numbering Rows in Result Set
Sql Server 2005 Using Charindex() to Split a String
How to Find What Foreign Key References an Index on Table
Is Count(*) in SQL Server a Constant Time Operation? If Not, Why Not