Entity Framework 6.1 (code-first) has added the possibility of adding indexes via the IndexAttribute
. The attribute takes a parameter for specifying whether the index should be clustered or non-clustered.
At the same time, AFAIK, Entity Framework requires every entity to have a primary key (annotated with the KeyAttribute
), and that primary key is always created as a clustered key.
Therefore, as soon as I apply the IndexAttribute
with IsClustered = true
, I get an error because, due to the key, there already is a clustered index.
So, how can I create a clustered index that is not the primary key using the IndexAttribute
? Is the IsClustered
property of the IndexAttribute
usable at all?
(For a little more context: I'm mapping a table that is only used for reading via LINQ queries. I do not need to actually insert, update, or delete entities from that table. Therefore, I don't need a primary key at all. Ideally, I'd like a table without a primary key, but with a non-unique, clustered index optimized for reading.)
Edit (2014-04-11): See also https://entityframework.codeplex.com/workitem/2212.
EF Core only supports one index per distinct set of properties. If you configure an index on a set of properties that already has an index defined, either by convention or previous configuration, then you will be changing the definition of that index.
Both clustered and nonclustered indexes can be unique. This means no two rows can have the same value for the index key. Otherwise, the index is not unique and multiple rows can share the same key value. For more information, see Create unique indexes.
A Clustered index is a type of index in which table records are physically reordered to match the index. A Non-Clustered index is a special type of index in which logical order of index does not match physical stored order of the rows on disk. The size of clustered index is large.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With