以下完整工作示例中未设置索引。这正是what I see in Visual Studio in my actual project:
第一次通过。从UnitTest添加1190行。这是context.Database.Log事件中显示的插入之一。
所以我插入一行。 INSERT INTO程序(DispalyName .... 田田。完整的索引,****但只有一个插入叶****。
所以我再次运行测试以添加另外1190行。正如所料。 现在一切都搞定了指数。看看**** 1191叶子,但程序表****中有2381行。
正在创建索引但是当它作为关系添加时,它不使用索引。没有创建索引。
如果我改变:
//Join the relations
host.Programs.Add(program);
ctx.Hosts.Add(host);
//Save
ctx.SaveChanges();
要
ctx.Programs.Add(program);
//Save
ctx.SaveChanges();
索引有效,我就离开了。有什么想法吗?
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);
}
}
这是控制台的输出:
INSERT [dbo] .Host VALUES(@ 0)SELECT [Id] FROM [dbo]。[Host] WHERE @@ ROWCOUNT&gt; 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&gt; 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)
如果我真的针对一个空数据库运行它,它就可以工作。
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