Вы можете создать атрибут с именем indexed (как вы предложили), который затем будет выбран в пользовательском инициализаторе.
Я создал следующий атрибут:
[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; }
}
Затем я создал собственный инициализатор, который получил список имен таблиц, созданных для сущностей в моем контексте. У меня есть два базовых класса, которые наследуют все мои сущности, поэтому я сделал следующее, чтобы получить имена таблиц:
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);
Затем я нашел все свойства в каждом объекте, которые имеют этот атрибут, а затем выполнил команду SQL, чтобы сгенерировать индекс для каждого свойства. Классно!
//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)
{
}
}
}
Я даже продолжал добавлять индексы на основе классов (которые могут иметь несколько столбцов), уникальные ограничения и ограничения по умолчанию - все одинаково. Что действительно хорошо, так это то, что если вы поместите эти атрибуты в унаследованный класс, индекс или ограничение будут применены ко всем классам (таблицам), которые его наследуют.
Кстати, вспомогательный помощник содержит следующее:
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");
}
}
}