2015-10-01 9 views
19

मैं पहले ईएफ 6.1.x कोड का उपयोग करता हूं।इकाई फ्रेमवर्क फ़िल्टर इंडेक्स

मैंने पढ़ा है कि फ़िल्टर अभिव्यक्ति वाला इंडेक्स ईएफ नवीनतम द्वारा समर्थित नहीं है।

EF 6.1 Unique Nullable Index

एक साल बाद, कोड पहला और DbMigrations के साथ एक फ़िल्टर सूचकांक बनाने पर कार्य कर रास्ता क्या है:

वहाँ भी इतने पर कोई समाधान नहीं है?

CREATE UNIQUE NONCLUSTERED INDEX [IX_DefaultLanguageApplicationId] ON [dbo].[Languages] 
(
    [IsDefaultLanguage] ASC, 
    [ApplicationId] ASC, 
) 
WHERE ([IsDefaultLanguage]=(1)) 
+0

दिलचस्प लेख: http://stackoverflow.com/questions/29922099/how-to-add-an-index-on-multiple-columns-with-asc-desc-sort-using-the-fluent-api – Elisabeth

उत्तर

20

एफई 6.1, कोड पहला और DbMigrations के साथ इस काम करने के लिए काम कर रहे रास्ता DbMigration कक्षा में Sql विधि का उपयोग करने के लिए है:

public partial class AddIndexes : DbMigration 
{ 
    public override void Up() 
    { 
     Sql(@"CREATE UNIQUE NONCLUSTERED INDEX 
      [IX_DefaultLanguageApplicationId] ON [dbo].[Languages] 
      (
       [IsDefaultLanguage] ASC, 
       [ApplicationId] ASC 
      ) 
      WHERE ([IsDefaultLanguage]=(1))"); 

    } 

    public override void Down() 
    { 
     DropIndex("dbo.Languages", "IX_DefaultLanguageApplicationId"); 
    } 
} 

लेकिन मुझे लगता है कि आप शायद पूछ रहे हैं यदि आप create an index using the IndexAttribute introduced in 6.1 कर सकते हैं, लेकिन एक फिल्टर के साथ - इसका जवाब

लगभग का डुप्लिकेट है "नहीं": Entity Framework 6.1 - Create index with INCLUDE statement

+0

हां, मैं http://blog.oneunicorn.com/2014/02/15/ef-6-1-creating-indexes-with-indexattribute/ ढूंढ रहा हूं लेकिन मुझे पता था कि वास्तव में यह अभी तक संभव नहीं है। अभी भी धन्यवाद! – Elisabeth

+0

मैंने इस आंशिक वर्ग को जोड़ा है और "अपडेट-डेटाबेस" किया है तो सभी माइग्रेशन स्पष्ट रूप से लागू हो गए हैं लेकिन यह नई अनुक्रमणिका डेटाबेस में नहीं बनाई गई ??? – Elisabeth

+0

ठीक है मैंने पहले एक खाली माइग्रेटिन बनाया लेकिन फिर मुझे यह त्रुटि मिल गई: त्रुटि संख्या: 102, राज्य: 1, कक्षा: 15 ') के पास गलत वाक्यविन्यास। क्या आप कृपया ")" त्रुटि को सही करेंगे? – Elisabeth

1

मुझे पता है कि मूल पोस्ट ईएफ के 6.1 संस्करण को संदर्भित करता है, लेकिन कुछ शोध के बाद मुझे ईएफ कोर (1.1 संस्करण) की धाराप्रवाह एपीआई में फ़िल्टर किए गए इंडेक्स के लिए एक विस्तार विधि जोड़ने का एक तरीका मिला है। शायद किसी को यह उपयोगी लगेगा (और शायद पुराने संस्करणों में इसे लागू करने का एक तरीका भी है)। मुझे आपको चेतावनी देना है हालांकि। चूंकि यह समाधान Microsoft.EntityFrameworkCore.Migrations.Internal और Microsoft.EntityFrameworkCore.Infrastructure नामस्थानों से कक्षाओं का उपयोग करता है, इसलिए यह गारंटी नहीं है कि ईएफ अपडेट होने के बाद यह कोड काम करेगा। वहाँ एक मालिश इन नामस्थान के भीतर प्रत्येक वर्ग का एक सारांश में शामिल करते हुए कहा कि

This API may change or be removed in future releases

है, तो आप चेतावनी दी गई है।

लेकिन बिंदु पर।

सबसे पहले आपको IndexBuilder के लिए मानक एक्सटेंशन विधि बनाना है। इसकी मुख्य ज़िम्मेदारी निर्माण सूचकांक की स्थिति के साथ एक नई एनोटेशन जोड़ने जा रही है। एक तरफ एपीआई के साथ बाद में इस विधि का उपयोग करेगा। कृपया हमारी एनोटेशन SqlServer:FilteredIndex पर कॉल करें।

static class FilteredIndexExtension 
{ 
    public static IndexBuilder Filtered(this IndexBuilder indexBuilder, string condition) 
    { 
     indexBuilder.HasAnnotation("SqlServer:FilteredIndex", condition); 

     return indexBuilder; 
    } 
} 

अगला यह व्याख्या वास्तव में माइग्रेशन के अंदर शामिल किए जाने की अनुमति देने के लिए किया है। इंडेक्स बिल्डर्स के लिए आपको SqlServerMigrationsAnnotationProvider के डिफ़ॉल्ट व्यवहार को ओवरराइड करना होगा।

class ExtendedSqlServerMigrationsAnnotationProvider : SqlServerMigrationsAnnotationProvider 
{ 
    public override IEnumerable<IAnnotation> For(IIndex index) 
    { 
     var baseAnnotations = base.For(index); 
     var customAnnotatinos = index.GetAnnotations().Where(a => a.Name == "SqlServer:FilteredIndex"); 

     return baseAnnotations.Concat(customAnnotatinos); 
    } 
} 

अब सबसे कठिन हिस्सा आता है। हमें इंडेक्स के संबंध में SqlServerMigrationsSqlGenerator के डिफ़ॉल्ट व्यवहार को ओवरराइड करना होगा।

class ExtendedSqlServerMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator 
{ 
    public ExtendedSqlServerMigrationsSqlGenerator(IRelationalCommandBuilderFactory commandBuilderFactory, ISqlGenerationHelper sqlGenerationHelper, IRelationalTypeMapper typeMapper, IRelationalAnnotationProvider annotations, IMigrationsAnnotationProvider migrationsAnnotations) : base(commandBuilderFactory, sqlGenerationHelper, typeMapper, annotations, migrationsAnnotations) 
    { 
    } 

    protected override void Generate(CreateIndexOperation operation, IModel model, MigrationCommandListBuilder builder, bool terminate) 
    { 
     base.Generate(operation, model, builder, false); 

     var filteredIndexCondition = operation.FindAnnotation("SqlServer:FilteredIndex"); 

     if (filteredIndexCondition != null) 
      builder.Append($" WHERE {filteredIndexCondition.Value}"); 

     if (terminate) 
     { 
      builder.AppendLine(SqlGenerationHelper.StatementTerminator); 
      EndStatement(builder); 
     } 
    } 
} 

आप देख सकते हैं, हम आधार जनरेटर यहाँ, बुला रहे हैं तो हमारे हालत यह बदले बिना यह के अंत में जोड़ दिया जाएगा। हमें याद रखना होगा कि यहां बेस एसक्यूएल स्टेटमेंट को समाप्त नहीं करना है (base.Generate विधि को अंतिम तर्क false है)। यदि हमारी एनोटेशन सेट है तो हम SQL कथन के अंत में WHERE खंड के बाद अपना मान जोड़ सकते हैं। उसके बाद, इस विधि को पारित तर्क के आधार पर, हम आखिरकार कथन को समाप्त कर सकते हैं या इसे छोड़ सकते हैं।

काम करने के लिए उन सभी भागों के लिए हम अपने DbContext की OnConfiguring विधि अधिभावी द्वारा अपने नए संस्करणों के साथ पुराने सेवाओं को बदलने के लिए।

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
    { 
     optionsBuilder.ReplaceService<SqlServerMigrationsAnnotationProvider, ExtendedSqlServerMigrationsAnnotationProvider>(); 
     optionsBuilder.ReplaceService<SqlServerMigrationsSqlGenerator, ExtendedSqlServerMigrationsSqlGenerator>(); 
    } 

अब हम इस तरह हमारे विस्तार विधि का उपयोग कर सकते हैं:

builder.HasIndex(a => a.Identity).IsUnique().Filtered("[End] IS NULL"); 

यह इस तरह पलायन उत्पन्न करेगा:

migrationBuilder.CreateIndex(
      name: "IX_Activities_Identity", 
      table: "Activities", 
      column: "Identity", 
      unique: true) 
      .Annotation("SqlServer:FilteredIndex", "[End] IS NULL"); 

और पैकेज प्रबंधक कंसोल में Script-Migration commad बुला के बाद हम देखेंगे परिणामी एसक्यूएल इस प्रकार है:

CREATE UNIQUE INDEX [IX_Activities_Identity] ON [Activities] ([Identity]) WHERE [End] IS NULL; 

इस विधि का उपयोग वास्तव में किसी भी कस्टम एसक्यूएल जनरेटर को ef core fluent api में शामिल करने के लिए किया जा सकता है। कम से कम जब तक ईएफ एपीआई वही रहता है।

संबंधित मुद्दे