Entity Framework Code First Fluent Api: Adding Indexes to columns

前端 未结 15 1363
一生所求
一生所求 2020-11-30 17:43

I\'m running EF 4.2 CF and want to create indexes on certain columns in my POCO objects.

As an example lets say we have this employee class:

public c         


        
15条回答
  •  死守一世寂寞
    2020-11-30 18:04

    You could create an attribute called indexed (as you suggested), which is then picked up in a custom initializer.

    I created the following attribute:

    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
    public class IndexAttribute : Attribute
    {
        public IndexAttribute(bool isUnique = false, bool isClustered = false, SortOrder sortOrder = SortOrder.Ascending)
        {
            IsUnique = isUnique;
            IsClustered = isClustered;
            SortOrder = sortOrder == SortOrder.Unspecified ? SortOrder.Ascending : sortOrder;
    
        }
    
        public bool IsUnique { get; private set; }
        public bool IsClustered { get; private set; }
        public SortOrder SortOrder { get; private set; }
        //public string Where { get; private set; }
    }
    

    I then created a custom initializer which got a list of the table names created for the entities in my context. I have two base classes which all my entities inherit, so I did the following to get the table names:

     var baseEF = typeof (BaseEFEntity);
            var baseLink = typeof (BaseLinkTable);
            var types =
                AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany(s => s.GetTypes()).Where(
                    baseEF.IsAssignableFrom).Union(AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany(
                        s => s.GetTypes()).Where(
                            baseLink.IsAssignableFrom));
    
            var sqlScript = context.ObjectContext.CreateDatabaseScript();
    
            foreach (var type in types)
            {
                var table = (TableAttribute) type.GetCustomAttributes(typeof (TableAttribute), true).FirstOrDefault();
                var tableName = (table != null ? table.Name : null) ?? Pluralizer.Pluralize(type.Name);
    

    I then found all the properties on each entity that have this attribute and then execute a SQL command to generate the index on each property. Sweet!

    //Check that a table exists
                if (sqlScript.ToLower().Contains(string.Format(CREATETABLELOOKUP, tableName.ToLower())))
                {
    
                    //indexes
    
                    var indexAttrib = typeof (IndexAttribute);
                    properties = type.GetProperties().Where(prop => Attribute.IsDefined(prop, indexAttrib));
                    foreach (var property in properties)
                    {
                        var attributes = property.GetCustomAttributes(indexAttrib, true).ToList();
    
                        foreach (IndexAttribute index in attributes)
                        {
                            var indexName = string.Format(INDEXNAMEFORMAT, tableName, property.Name,
                                                          attributes.Count > 1
                                                              ? UNDERSCORE + (attributes.IndexOf(index) + 1)
                                                              : string.Empty);
                            try
                            {
                                context.ObjectContext.ExecuteStoreCommand(
                                    string.Format(INDEX_STRING, indexName,
                                                  tableName,
                                                  property.Name,
                                                  index.IsUnique ? UNIQUE : string.Empty,
                                                  index.IsClustered ? CLUSTERED : NONCLUSTERED,
                                                  index.SortOrder == SortOrder.Ascending ? ASC : DESC));
                            }
                            catch (Exception)
                            {
                            }
                        }
                    }
    

    I even went on to add class based indexes (which could have multiple columns) , unique constraints and default constraints all in the same way. Whats also really nice is that if you put these attributes on an inherited class the index or constraint gets applied to all the classes (tables) that inherit it.

    BTW the pluralizer helper contains the following:

    public static class Pluralizer
    {
        private static object _pluralizer;
        private static MethodInfo _pluralizationMethod;
    
        public static string Pluralize(string word)
        {
            CreatePluralizer();
            return (string) _pluralizationMethod.Invoke(_pluralizer, new object[] {word});
        }
    
        public static void CreatePluralizer()
        {
            if (_pluralizer == null)
            {
                var aseembly = typeof (DbContext).Assembly;
                var type =
                    aseembly.GetType(
                        "System.Data.Entity.ModelConfiguration.Design.PluralizationServices.EnglishPluralizationService");
                _pluralizer = Activator.CreateInstance(type, true);
                _pluralizationMethod = _pluralizer.GetType().GetMethod("Pluralize");
            }
        }
    }
    

提交回复
热议问题