Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.net Core Entity Framework cannot find IndexAttribute

I receive the following from Visual Studio Code on my Mac, both in IDE and console window after executing "dotnet run":

The type or namespace name 'IndexAttribute' could not be found

I have a class called Story which I want to use for generating a database with Code First. This class has a primary key marked with KeyAttribute and Author string marked with MaxLengthAttribute, so both of those work (using System.ComponentModel.DataAnnotations). Two more fields, DateTime Date and bool IsPublished, have IndexAttribute applied (it's a two-column index). I explicitly named it IX_DatePublished, IsUnique = false, and use Order = 1 for the Date field and Order = 2 for the IsPublished field.

  • What do I put in project.json before running "dotnet restore" to have it pull in the right stuff for IndexAttribute to work?
  • Does EF included with ASPCore1 for Mac/Linux not have the right namespace included?

Thank you!

like image 914
Valeriy Novytskyy Avatar asked Jul 22 '16 16:07

Valeriy Novytskyy


1 Answers

I am still in the process of getting familiar with Core tools; further research revealed that this feature is not supported but they would consider a pull request.

https://github.com/aspnet/EntityFrameworkCore/issues/4050

The work-around

The recommended way to add indexes to Code First models in the absence of IndexAttribute is to use Entity Framework Fluent API. For example the following could be added to your context (derived from DbContext):

    /// <summary>
    /// Creates database structure not supported with Annotations using Fluent syntax.
    /// </summary>
    /// <param name="optionsBuilder">The configuration interface.</param>
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Story>().HasIndex(
            story => new { story.Date, story.Published }).IsUnique(false);
    }

This creates a two-column index for Story.Date and Story.Published that's not unique. Following this change, use:

dotnet ef migrations add <name>
dotnet ef database update

It's interesting to note what kind of Migration code is generated to create this index (you could use this directly to customize your migrations to create index instead of adding code to your Context class):

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "Stories",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("Autoincrement", true),
            Author = table.Column<string>(maxLength: 64, nullable: true),
            Date = table.Column<DateTime>(nullable: false),
            Published = table.Column<bool>(nullable: false),
            Title = table.Column<string>(nullable: true)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Stories", x => x.Id);
        });

    migrationBuilder.CreateIndex(
        name: "IX_Stories_Date_Published",
        table: "Stories",
        columns: new[] { "Date", "Published" });
}

The fruit of such labors:

SQLiteStudio showing the generated table

like image 167
Valeriy Novytskyy Avatar answered Sep 28 '22 15:09

Valeriy Novytskyy