3

I'm working with unique indexes in a code-first environment. They are defined like this:

modelBuilder.Entity<Foo>().HasIndex(foo => foo.Bar).IsUnique()

Using Entity Framework's metadata model, I would like to programmatically get a list of indexes (or constraints) given a specified type (Foo in this case).

Doing similar things with EF have proven to be relatively easy. For example, you can get a list of property names that are the primary key of a specified set, like so: Entity Framework code first. Find primary key. Entity Framework also convieniently exposes navigation properties through similar methods: EF5 How to get list of navigation properties for a domain object.

Is there something similar available for (unique) indexes?


EDIT: Example DbContext:

public class Foo
{
    public int Id { get; set; }

    [Index]
    public int SomeNumber { get; set; }
}

public class FooContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }

    public FooContext() : base("DefaultConnection") { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

Using this DbContext, @Kahbazi's method of obtaining the PropertyIndexes doesn't work, it will be an empty collection.

When I use the fluent API instead of an explicit DbSet, with the following code:

modelBuilder.Entity<Foo>().HasIndex(foo => foo.SomeNumber);

... then "Configuration" (see @Kahbazi's answer) will disappear from the MetadataProperties, resulting in System.InvalidOperationException: 'Sequence contains no matching element'

Rudey
  • 4,717
  • 4
  • 42
  • 84

1 Answers1

2

You can use this code to get the indexes

Context context = new Context();
IObjectContextAdapter objectContextAdapter = (IObjectContextAdapter)context;

object configuration = objectContextAdapter.ObjectContext.CreateObjectSet<Foo>()
    .EntitySet
    .MetadataProperties
    .Where(x => x.Name == "Configuration")
    .First()
    .Value;

var propertyIndexes = configuration.GetType().GetProperty("PropertyIndexes", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(configuration);
var list = (System.Collections.IEnumerable)propertyIndexes;
foreach (var item in list)
{
    Console.WriteLine(item);
}

But since most of the classes are internal, you have to use Reflection

Kahbazi
  • 14,331
  • 3
  • 45
  • 76