public class SomeClass { public int Id { get; set; } [Index] public string Name { get; set; } [FullTextIndex] public string Description { get; set; } }
public class IndexAttribute : Attribute { } public class FullTextIndexAttribute : Attribute { } public class FullTextIndex { public enum SearchAlgorithm { Contains, FreeText } }
public abstract class DbContextIndexed : DbContext { private static bool Complete; private int? language; public int Language { get { return language.HasValue ? language.Value : 1049; //1049 - } set { language = value; } } protected override void Dispose(bool disposing) { if (!Complete) { Complete = true; CalculateIndexes(); } base.Dispose(disposing); } private void CalculateIndexes() { if (GetCompleteFlag()) return; // DbContext foreach (var property in this.GetType() .GetProperties() .Where(f => f.PropertyType.BaseType != null && f.PropertyType.BaseType.Name == "DbQuery`1")) { var currentEntityType = property.PropertyType.GetGenericArguments().FirstOrDefault(); if (currentEntityType == null || currentEntityType.BaseType.FullName != "System.Object") continue; // var tableAttribute = currentEntityType .GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault() as TableAttribute; var tableName = tableAttribute != null ? tableAttribute.Name : property.Name; // Index, BuildingIndexes(tableName, currentEntityType.GetProperties() .Where(f => f.GetCustomAttributes(typeof(IndexAttribute), false) .Any())); // FullTextIndex, BuildingFullTextIndexes(tableName, currentEntityType.GetProperties() .Where(f => f.GetCustomAttributes(typeof(FullTextIndexAttribute), false) .Any())); } CreateCompleteFlag(); } private void BuildingIndexes(string tableName, IEnumerable<PropertyInfo> propertyes) { foreach (var property in propertyes) Database.ExecuteSqlCommand(String.Format("CREATE INDEX IX_{0} ON {1} ({0})", property.Name, tableName)); } private void BuildingFullTextIndexes(string tableName, IEnumerable<PropertyInfo> propertyes) { var fullTextColumns = string.Empty; foreach (var property in propertyes) fullTextColumns += String.Format("{0}{1} language {2}", (string.IsNullOrWhiteSpace(fullTextColumns) ? null : ","), property.Name, Language); // Database.ExecuteSqlCommand(System.Data.Entity.TransactionalBehavior.DoNotEnsureTransaction, String.Format("IF NOT EXISTS (SELECT * FROM sysindexes WHERE id=object_id('{1}') and name='IX_{2}') CREATE UNIQUE INDEX IX_{2} ON {1} ({2}); CREATE FULLTEXT CATALOG FTXC_{1} AS DEFAULT; CREATE FULLTEXT INDEX ON {1}({0}) KEY INDEX [IX_{2}] ON [FTXC_{1}]", fullTextColumns, tableName, "Id")); } private void CreateCompleteFlag() { Database.ExecuteSqlCommand(System.Data.Entity.TransactionalBehavior.DoNotEnsureTransaction, "CREATE TABLE [dbo].[__IndexBuildingHistory]( [DataContext] [nvarchar](255) NOT NULL, [Complete] [bit] NOT NULL, CONSTRAINT [PK___IndexBuildingHistory] PRIMARY KEY CLUSTERED ([DataContext] ASC))"); } private bool GetCompleteFlag() { var queryResult = Database.SqlQuery(typeof(string), "IF OBJECT_ID('__IndexBuildingHistory', 'U') IS NOT NULL SELECT 'True' AS 'Result' ELSE SELECT 'False' AS 'Result'") .GetEnumerator(); queryResult.MoveNext(); return bool.Parse(queryResult.Current as string); } }
public static class IQueryableExtension { public static IQueryable<T> FullTextSearch<T>(this DbSet<T> queryable, Expression<Func<T, bool>> func, FullTextIndex.SearchAlgorithm algorithm = FullTextIndex.SearchAlgorithm.FreeText) where T : class { var internalSet = queryable.AsQueryable() .GetType() .GetProperty("System.Data.Entity.Internal.Linq.IInternalSetAdapter.InternalSet", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(queryable.AsQueryable()); var entitySet = (EntitySet)internalSet.GetType() .GetProperty("EntitySet") .GetValue(internalSet); var searchType = algorithm == FullTextIndex.SearchAlgorithm.Contains ? "CONTAINS" : "FREETEXT"; var columnName = ((MemberExpression)((BinaryExpression)func.Body).Left).Member.Name; var searchPattern = ((ConstantExpression)((BinaryExpression)func.Body).Right).Value; return queryable.SqlQuery( String.Format("SELECT * FROM {0} WHERE {1};", entitySet.Name, String.Format("{0}({1},'{2}')", searchType, columnName, searchPattern))) .AsQueryable(); } }
public class Animal { public int Id { get; set; } [Index] [StringLength(200)] public string Name { get; set; } [FullTextIndex] public string Description { get; set; } public int Family { get; set; } [FullTextIndex] public string AdditionalDescription { get; set; } }
public class DataContext : DbContextIndexed { public DbSet<Animal> Animals { get; set; } }
static void Main(string[] args) { using (var context = new DataContext()) { var temp = context.Animals.ToList(); } }
<configuration> <connectionStrings> <add name="DataContext" connectionString="Data Source=(local)\SQL; Initial Catalog=EFCF; Integrated Security=true;" providerName="System.Data.SqlClient"/> </connectionStrings> </configuration>
using (var context = new DataContext()) { context.Animals.Add(new Animal { Name = "", Description = " , ." }); context.Animals.Add(new Animal { Name = "", Description = " , ." }); context.Animals.Add(new Animal { Name = "", Description = " - ." }); context.Animals.Add(new Animal { Name = "", Description = " ." }); context.Animals.Add(new Animal { Name = "", Description = " ." }); context.Animals.Add(new Animal { Name = " ", Description = " , ." }); context.SaveChanges(); }
using (var context = new DataContext()) { foreach (var pet in context.Animals.FullTextSearch(f => f.Description == "")) Console.WriteLine("{0} - {1}", pet.Name, pet.Description); }
Source: https://habr.com/ru/post/189806/
All Articles