复合索引不在Entity Framework中处理关系

时间:2015-12-10 05:04:27

标签: sql sql-server entity-framework

以下完整工作示例中未设置索引。这正是what I see in Visual Studio in my actual project

第一次通过。从UnitTest添加1190行。这是context.Database.Log事件中显示的插入之一。 enter image description here

EF显然创建了索引 enter image description here

到底是什么?我的索引未列出。 enter image description here

所以我插入一行。 INSERT INTO程序(DispalyName .... 田田。完整的索引,****但只有一个插入叶****。 enter image description here

正如所料,我现在有1191行 enter image description here

所以我再次运行测试以添加另外1190行。正如所料。 现在一切都搞定了指数。看看**** 1191叶子,但程序表****中有2381行。 enter image description here

最后真正的问题。执行计划没有说明使用索引。 enter image description here

正在创建索引但是当它作为关系添加时,它不使用索引。没有创建索引。

如果我改变:

//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

0 个答案:

没有答案