Myślę, że to fajny pomysł, ale musisz to zrobić sam, nie ma dla niego wbudowanej obsługi. Jeśli masz warstwę dostępu, możesz to zrobić tam. Potrzebujesz klasy atrybutów, czegoś takiego;
public enum IndexConstraints
{
Normal = 0x00000001, // Ascending, non-indexed
Descending = 0x00000010,
Unique = 0x00000100,
Sparse = 0x00001000, // allows nulls in the indexed fields
}
// Applied to a member
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class EnsureIndexAttribute : EnsureIndexes
{
public EnsureIndex(IndexConstraints ic = IndexConstraints.Normal) : base(ic) { }
}
// Applied to a class
[AttributeUsage(AttributeTargets.Class)]
public class EnsureIndexesAttribute : Attribute
{
public bool Descending { get; private set; }
public bool Unique { get; private set; }
public bool Sparse { get; private set; }
public string[] Keys { get; private set; }
public EnsureIndexes(params string[] keys) : this(IndexConstraints.Normal, keys) {}
public EnsureIndexes(IndexConstraints ic, params string[] keys)
{
this.Descending = ((ic & IndexConstraints.Descending) != 0);
this.Unique = ((ic & IndexConstraints.Unique) != 0); ;
this.Sparse = ((ic & IndexConstraints.Sparse) != 0); ;
this.Keys = keys;
}
}//class EnsureIndexes
Następnie możesz zastosować atrybuty na poziomie klasy lub członka w następujący sposób. Zauważyłem, że dodawanie na poziomie elementu członkowskiego było mniej prawdopodobne, aby nie było zsynchronizowane ze schematem w porównaniu z dodawaniem na poziomie klasy. Musisz się oczywiście upewnić, że otrzymasz rzeczywistą nazwę elementu, a nie nazwę członka C#;
[CollectionName("People")]
//[EnsureIndexes("k")]// doing it here would allow for multi-key configs
public class Person
{
[BsonElement("k")] // name mapping in the DB schema
[BsonIgnoreIfNull]
[EnsureIndex(IndexConstraints.Unique|IndexConstraints.Sparse)] // name is implicit here
public string userId{ get; protected set; }
// other properties go here
}
a następnie w implementacji dostępu do bazy danych (lub repozytorium) potrzebujesz czegoś takiego;
private void AssureIndexesNotInlinable()
{
// We can only index a collection if there's at least one element, otherwise it does nothing
if (this.collection.Count() > 0)
{
// Check for EnsureIndex Attribute
var theClass = typeof(T);
// Walk the members of the class to see if there are any directly attached index directives
foreach (var m in theClass.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
{
List<string> elementNameOverride = new List<string>(1);
EnsureIndexes indexAttr = null;
// For each members attribs
foreach (Attribute attr in m.GetCustomAttributes())
{
if (attr.GetType() == typeof(EnsureIndex))
indexAttr = (EnsureIndex)attr;
if (attr.GetType() == typeof(RepoElementAttribute))
elementNameOverride.Add(((RepoElementAttribute)attr).ElementName);
if ((indexAttr != null) && (elementNameOverride.Count != 0))
break;
}
// Index
if (indexAttr != null)
{
if (elementNameOverride.Count() > 0)
EnsureIndexesAsDeclared(indexAttr, elementNameOverride);
else
EnsureIndexesAsDeclared(indexAttr);
}
}
// Walk the atributes on the class itself. WARNING: We don't validate the member names here, we just create the indexes
// so if you create a unique index and don't have a field to match you'll get an exception as you try to add the second
// item with a null value on that key
foreach (Attribute attr in theClass.GetCustomAttributes(true))
{
if (attr.GetType() == typeof(EnsureIndexes))
EnsureIndexesAsDeclared((EnsureIndexes)attr);
}//foreach
}//if this.collection.count
}//AssureIndexesNotInlinable()
W takim przypadku usługa Upewnij się, że indeksy wyglądają tak;
private void EnsureIndexesAsDeclared(EnsureIndexes attr, List<string> indexFields = null)
{
var eia = attr as EnsureIndexes;
if (indexFields == null)
indexFields = eia.Keys.ToList();
// use driver specific methods to actually create this index on the collection
var db = GetRepositoryManager(); // if you have a repository or some other method of your own
db.EnsureIndexes(indexFields, attr.Descending, attr.Unique, attr.Sparse);
}//EnsureIndexes()
Pamiętaj, że umieścisz to po każdej aktualizacji, ponieważ jeśli gdzieś zapomnisz, Twoje indeksy mogą nie zostać utworzone. Dlatego ważne jest, aby upewnić się, że zoptymalizowałeś wywołanie, aby szybko wróciło, jeśli nie ma indeksowania do zrobienia przed przejściem przez cały ten kod odbicia. Najlepiej byłoby zrobić to tylko raz, a przynajmniej raz na uruchomienie aplikacji. Jednym ze sposobów byłoby użycie flagi statycznej do śledzenia, czy już to zrobiłeś, i potrzebujesz dodatkowej ochrony przed blokadą, ale w uproszczeniu wygląda to mniej więcej tak;
void AssureIndexes()
{
if (_requiresIndexing)
AssureIndexesInit();
}
Więc to jest metoda, której będziesz potrzebować w każdej wykonanej aktualizacji bazy danych, która, jeśli masz szczęście, zostanie również uwzględniona przez optymalizator JIT.