Indexes are not being set when inserting rows in the following, fully-working example. The index is being created but when it's being added as a relationship, it's not using the index. No index leaves get created. This is what I'm seeing. http://imgur.com/a/ctvVP
If I change:
//Join the relations
host.Programs.Add(program);
ctx.Hosts.Add(host);
//Save
ctx.SaveChanges();
To
ctx.Programs.Add(program);
//Save
ctx.SaveChanges();
The index works and I get leaves. Any ideas?
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Infrastructure.Annotations;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Configuration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.SqlClient;
using System.IO;
namespace dbtest
{
class ProgramTest
{
static void Main(string[] args)
{
//Uses nuget package LocalDbApi
//Start a localdb instance. Delete the old one if necessary
var localDb = new LocalDbApi.Instance();
try { localDb.StopInstance("dust");} catch { }
if (File.Exists("c:\\users\\james\\test.mdf")) File.Delete("c:\\users\\james\\test.mdf");
if (File.Exists("c:\\users\\james\\test_log.ldf")) File.Delete("c:\\users\\james\\test_log.ldf");
try { localDb.GetInstance("dust"); } catch { localDb.Create("dust"); }
localDb.StartInstance("dust");
//Create the Db
Database.SetInitializer(new CreateDatabaseIfNotExists<DustContext>());
using (var ctx = new DustContext())
{
ctx.Database.Log = Console.Write;
ctx.Database.Create();
//Add the data
var host = new Host()
{
Hostname = "192.168.0.1",
Programs = new List<Program>()
};
var program = new Program()
{
DisplayName = "foo",
Architecture = 1,
Disposition = 0,
Publisher = "bar",
Version = "14684"
};
//Join the relations
host.Programs.Add(program);
ctx.Hosts.Add(host);
//Save
ctx.SaveChanges();
}
Console.Write("Press any key to continue ...");
Console.ReadKey();
}
public class DustContext : DbContext
{
public DbContextConfiguration Config => Configuration;
//My models
public DbSet<Program> Programs { get; set; }
public DbSet<Host> Hosts { get; set; }
//Connection String
public DustContext() : base(new SqlConnection() { ConnectionString = @"data source = (LocalDb)\dust;Trusted_Connection=False;Integrated Security=true;AttachDbFilename=c:\users\james\test.mdf" }, true) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new ProgramMap());
}
}
}
/***************************************************************
*
* Entities
*
***************************************************************/
public class Program
{
public int Id { get; set; }
//Composite key on these three
public string DisplayName { get; set; }
public string Publisher { get; set; }
public string Version { get; set; }
public Int32 Architecture { get; set; }
public int Disposition { get; set; }
}
public class ProgramMap : EntityTypeConfiguration<Program>
{
public ProgramMap()
{
Property(a => a.DisplayName)
.HasMaxLength(512)
.HasCompositeIndexAnnotation("IX_ProgramDisplayNamePublisherVersion", 1);
Property(a => a.Publisher)
.HasMaxLength(512)
.HasCompositeIndexAnnotation("IX_ProgramDisplayNamePublisherVersion", 2);
Property(a => a.Version)
.HasMaxLength(512)
.HasCompositeIndexAnnotation("IX_ProgramDisplayNamePublisherVersion", 3);
}
}
public class Host
{
public int Id { get; set; }
public string Hostname { get; set; }
public virtual List<Program> Programs { get; set; }
}
}
/// <summary>
/// Applies an index on composite columns
/// </summary>
internal static class TypeConfigurationExtensions
{
public static PrimitivePropertyConfiguration HasCompositeIndexAnnotation(
this PrimitivePropertyConfiguration property,
string indexName,
int columnOrder)
{
var indexAttribute = new IndexAttribute(indexName, columnOrder) { IsUnique = false };
var indexAnnotation = new IndexAnnotation(indexAttribute);
return property.HasColumnAnnotation(IndexAnnotation.AnnotationName, indexAnnotation);
}
}
Here's the output to the console:
> INSERT [dbo].[Host]([Hostname]) VALUES (@0) SELECT [Id] FROM [dbo].[Host] WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
> -- @0: '192.168.0.1' (Type = String, Size = -1)
> INSERT [dbo].[Program]([DisplayName], [Publisher], [Version], [Architecture], [D isposition], [Host_Id]) VALUES (@0, @1, @2, @3, @4, @5) SELECT [Id] FROM [dbo].[Program] WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
> -- @0: 'foo' (Type = String, Size = 512)
> -- @1: 'bar' (Type = String, Size = 512)
> -- @2: '14684' (Type = String, Size = 512)
> -- @3: '1' (Type = Int32)
> -- @4: '0' (Type = Int32)
> -- @5: '1' (Type = Int32)
If I actually run this against an empty database from Visual Studio, it works.
BEGIN TRAN T1
INSERT [dbo].Host VALUES ('192.168.0.1') SELECT [Id] FROM [dbo].[Host] WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
INSERT [dbo].[Program]([DisplayName], [Publisher], [Version], [Architecture], [Disposition], [Host_Id]) VALUES ('foo', 'bar', '14684', '1', '0', '1') SELECT [Id] FROM [dbo].[Program] WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
COMMIT TRAN T1