Quantcast
Viewing all articles
Browse latest Browse all 10

Answer by Legacy Code for How to convert an expression tree to a partial SQL query?

Extensions for the SimpleExpressionToSQL class

    public static class Extensions    {        private static readonly MethodInfo _deleteMethod;        private static readonly MethodInfo _deleteMethodAsync;        private static readonly MethodInfo _toSqlStringMethod;        private static readonly MethodInfo _updateMethod;        private static readonly MethodInfo _updateMethodAsync;        static Extensions()        {            Type extensionType = typeof(Extensions);            _deleteMethod = extensionType.GetMethod(nameof(Extensions.Delete), BindingFlags.Static | BindingFlags.Public);            _updateMethod = extensionType.GetMethod(nameof(Extensions.Update), BindingFlags.Static | BindingFlags.Public);            _deleteMethodAsync = extensionType.GetMethod(nameof(Extensions.DeleteAsync), BindingFlags.Static | BindingFlags.Public);            _updateMethodAsync = extensionType.GetMethod(nameof(Extensions.Update), BindingFlags.Static | BindingFlags.Public);            _toSqlStringMethod = extensionType.GetMethod(nameof(Extensions.ToSqlString), BindingFlags.Static | BindingFlags.Public);        }        public static bool CanConvertToSqlDbType(this Type type) => type.ToSqlDbTypeInternal().HasValue;        public static int Delete<T>(this IQueryable<T> queryable)        {            var simpleExpressionToSQL = new SimpleExpressionToSQL(queryable.AppendCall(_deleteMethod));            return simpleExpressionToSQL.ExecuteNonQuery();        }        public static async Task<int> DeleteAsync<T>(this IQueryable<T> queryable)        {            var simpleExpressionToSQL = new SimpleExpressionToSQL(queryable.AppendCall(_deleteMethodAsync));            return await simpleExpressionToSQL.ExecuteNonQueryAsync();        }        public static string GetTableName<TEntity>(this DbSet<TEntity> dbSet) where TEntity : class        {            DbContext context = dbSet.GetService<ICurrentDbContext>().Context;            IModel model = context.Model;            IEntityType entityTypeOfFooBar = model                .GetEntityTypes()                .First(t => t.ClrType == typeof(TEntity));            IAnnotation tableNameAnnotation = entityTypeOfFooBar.GetAnnotation("Relational:TableName");            return tableNameAnnotation.Value.ToString();        }        public static string GetTableName(this IQueryable query, Type entity)        {            QueryCompiler compiler = query.Provider.GetValueOfField<QueryCompiler>("_queryCompiler");            IModel model = compiler.GetValueOfField<IModel>("_model");            IEntityType entityTypeOfFooBar = model                .GetEntityTypes()                .First(t => t.ClrType == entity);            IAnnotation tableNameAnnotation = entityTypeOfFooBar.GetAnnotation("Relational:TableName");            return tableNameAnnotation.Value.ToString();        }        public static SqlDbType ToSqlDbType(this Type type) =>            type.ToSqlDbTypeInternal() ?? throw new InvalidCastException($"Unable to cast from '{type}' to '{typeof(DbType)}'.");        public static string ToSqlString<T>(this IQueryable<T> queryable) => new SimpleExpressionToSQL(queryable.AppendCall(_toSqlStringMethod));        public static int Update<TSource, TResult>(this IQueryable<TSource> queryable, Expression<Func<TSource, TResult>> selector)        {            var simpleExpressionToSQL = new SimpleExpressionToSQL(queryable.AppendCall(_updateMethod, selector));            return simpleExpressionToSQL.ExecuteNonQuery();        }        public static async Task<int> UpdateAsync<TSource, TResult>(this IQueryable<TSource> queryable, Expression<Func<TSource, TResult>> selector)        {            var simpleExpressionToSQL = new SimpleExpressionToSQL(queryable.AppendCall(_updateMethodAsync, selector));            return await simpleExpressionToSQL.ExecuteNonQueryAsync();        }        internal static DbContext GetDbContext(this IQueryable query)        {            QueryCompiler compiler = query.Provider.GetValueOfField<QueryCompiler>("_queryCompiler");            RelationalQueryContextFactory queryContextFactory = compiler.GetValueOfField<RelationalQueryContextFactory>("_queryContextFactory");            QueryContextDependencies dependencies = queryContextFactory.GetValueOfField<QueryContextDependencies>("_dependencies");            return dependencies.CurrentContext.Context;        }        internal static string Join(this IEnumerable<string> values, string separator) => string.Join(separator, values);        internal static bool RequiresQuotes(this SqlDbType sqlDbType)        {            switch (sqlDbType)            {                case SqlDbType.Char:                case SqlDbType.Date:                case SqlDbType.DateTime:                case SqlDbType.DateTime2:                case SqlDbType.DateTimeOffset:                case SqlDbType.NChar:                case SqlDbType.NText:                case SqlDbType.Time:                case SqlDbType.SmallDateTime:                case SqlDbType.Text:                case SqlDbType.UniqueIdentifier:                case SqlDbType.Timestamp:                case SqlDbType.VarChar:                case SqlDbType.Xml:                case SqlDbType.Variant:                case SqlDbType.NVarChar:                    return true;                default:                    return false;            }        }        internal static unsafe string ToCamelCase(this string value)        {            if (value == null || value.Length == 0)            {                return value;            }            string result = string.Copy(value);            fixed (char* chr = result)            {                char valueChar = *chr;                *chr = char.ToLowerInvariant(valueChar);            }            return result;        }        private static IQueryable<TResult> AppendCall<TSource, TResult>(this IQueryable<TSource> queryable, MethodInfo methodInfo, Expression<Func<TSource, TResult>> selector)        {            MethodInfo methodInfoGeneric = methodInfo.MakeGenericMethod(typeof(TSource), typeof(TResult));            MethodCallExpression methodCallExpression = Expression.Call(methodInfoGeneric, queryable.Expression, selector);            return new EntityQueryable<TResult>(queryable.Provider as IAsyncQueryProvider, methodCallExpression);        }        private static IQueryable<T> AppendCall<T>(this IQueryable<T> queryable, MethodInfo methodInfo)        {            MethodInfo methodInfoGeneric = methodInfo.MakeGenericMethod(typeof(T));            MethodCallExpression methodCallExpression = Expression.Call(methodInfoGeneric, queryable.Expression);            return new EntityQueryable<T>(queryable.Provider as IAsyncQueryProvider, methodCallExpression);        }        private static T GetValueOfField<T>(this object obj, string name)        {            FieldInfo field = obj                .GetType()                .GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);            return (T)field.GetValue(obj);        }        [SuppressMessage("Style", "IDE0011:Add braces", Justification = "Easier to read than with Allman braces")]        private static SqlDbType? ToSqlDbTypeInternal(this Type type)        {            if (Nullable.GetUnderlyingType(type) is Type nullableType)                return nullableType.ToSqlDbTypeInternal();            if (type.IsEnum)                return Enum.GetUnderlyingType(type).ToSqlDbTypeInternal();            if (type == typeof(long))            /**/                return SqlDbType.BigInt;            if (type == typeof(byte[]))          /**/                return SqlDbType.VarBinary;            if (type == typeof(bool))            /**/                return SqlDbType.Bit;            if (type == typeof(string))          /**/                return SqlDbType.NVarChar;            if (type == typeof(DateTime))        /**/                return SqlDbType.DateTime2;            if (type == typeof(decimal))         /**/                return SqlDbType.Decimal;            if (type == typeof(double))          /**/                return SqlDbType.Float;            if (type == typeof(int))             /**/                return SqlDbType.Int;            if (type == typeof(float))           /**/                return SqlDbType.Real;            if (type == typeof(Guid))            /**/                return SqlDbType.UniqueIdentifier;            if (type == typeof(short))           /**/                return SqlDbType.SmallInt;            if (type == typeof(object))          /**/                return SqlDbType.Variant;            if (type == typeof(DateTimeOffset))  /**/                return SqlDbType.DateTimeOffset;            if (type == typeof(TimeSpan))        /**/                return SqlDbType.Time;            if (type == typeof(byte))            /**/                return SqlDbType.TinyInt;            return null;        }    }

Viewing all articles
Browse latest Browse all 10

Trending Articles