Exemplo n.º 1
0
            private static Func <TEntity, IEnumerable <PropertyValue> > GetFunc()
            {
                // Expressions
                var addMethod   = typeof(List <PropertyValue>).GetMethod("Add", new[] { typeof(PropertyValue) });
                var obj         = Expression.Parameter(typeof(TEntity), "obj");
                var constructor = typeof(PropertyValue).GetConstructor(new[]
                {
                    typeof(string),
                    typeof(object),
                    typeof(ClassProperty)
                });

                // Set the body
                var properties = PropertyCache.Get <TEntity>();
                var body       = Expression.ListInit(
                    Expression.New(typeof(List <PropertyValue>)),
                    properties.Select(property =>
                {
                    var name          = Expression.Constant(property.GetMappedName());
                    var value         = Expression.Convert(Expression.Property(obj, property.PropertyInfo), typeof(object));
                    var propertyValue = Expression.New(constructor,
                                                       name,
                                                       value,
                                                       Expression.Constant(property));
                    return(Expression.ElementInit(addMethod, propertyValue));
                }));

                // Set the function value
                return(Expression
                       .Lambda <Func <TEntity, IEnumerable <PropertyValue> > >(body, obj)
                       .Compile());
            }
Exemplo n.º 2
0
        /// <summary>
        /// Append the stringified parameter as fields to the SQL Query Statement.
        /// </summary>
        /// <typeparam name="TEntity">The type of data entity object bound for the SQL Statement to be created.</typeparam>
        /// <param name="index">The parameter index.</param>
        /// <param name="prefix">The prefix to the parameters.</param>
        /// <returns>The current instance.</returns>
        public QueryBuilder ParametersAsFieldsFrom <TEntity>(int index = 0, string prefix = Constant.DefaultParameterPrefix)
            where TEntity : class
        {
            var fields = PropertyCache.Get <TEntity>()?.Select(property => property.GetUnquotedMappedName());

            return(Append(fields?.AsParametersAsFields(index, prefix).Join(", ")));
        }
Exemplo n.º 3
0
 /// <summary>
 /// Gets the instance of <see cref="ClassProperty"/> object from of the data entity based on name.
 /// </summary>
 /// <typeparam name="TEntity">The type of the data entity.</typeparam>
 /// <param name="propertyName">The property name.</param>
 /// <returns>An instance of <see cref="ClassProperty"/> object.</returns>
 private static ClassProperty GetClassProperty<TEntity>(string propertyName)
     where TEntity : class
 {
     var properties = PropertyCache.Get<TEntity>();
     return properties.FirstOrDefault(
         p => string.Equals(p.PropertyInfo.Name, propertyName, StringComparison.OrdinalIgnoreCase));
 }
Exemplo n.º 4
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        internal static ClassProperty GetProperty <TEntity>(PropertyInfo propertyInfo)
            where TEntity : class
        {
            if (propertyInfo == null)
            {
                return(null);
            }

            // Variables
            var properties = PropertyCache.Get <TEntity>();
            var name       = PropertyMappedNameCache.Get(propertyInfo);

            // Failing at some point - for base interfaces
            var property = properties
                           .FirstOrDefault(p =>
                                           string.Equals(p.GetMappedName(), name, StringComparison.OrdinalIgnoreCase));

            // Matches to the actual class properties
            if (property == null)
            {
                property = properties
                           .FirstOrDefault(p =>
                                           string.Equals(p.PropertyInfo.Name, name, StringComparison.OrdinalIgnoreCase));
            }

            // Return the value
            return(property);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates a new instance of <see cref="DataEntityDataReader{TEntity}"/> object.
        /// </summary>
        /// <param name="entities">The list of the data entity object to be used for manipulation.</param>
        /// <param name="connection">The actual <see cref="IDbConnection"/> object used.</param>
        /// <param name="transaction">The transaction object that is currently in used.</param>
        public DataEntityDataReader(IEnumerable <TEntity> entities, IDbConnection connection, IDbTransaction transaction)
        {
            if (entities == null)
            {
                throw new NullReferenceException("The entities could not be null.");
            }

            // Fields
            m_isClosed        = false;
            m_isDisposed      = false;
            m_position        = -1;
            m_recordsAffected = -1;

            // Properties
            if (connection != null)
            {
                var fields = DbFieldCache.Get(connection, ClassMappedNameCache.Get <TEntity>(), transaction);
                if (fields?.Any() == true)
                {
                    Properties = PropertyCache.Get <TEntity>()
                                 .Where(p => fields.FirstOrDefault(f => string.Equals(f.UnquotedName, p.GetUnquotedMappedName(), StringComparison.OrdinalIgnoreCase)) != null)
                                 .AsList();
                }
            }
            if (Properties == null)
            {
                Properties = PropertyCache.Get <TEntity>().AsList();
            }
            Enumerator = entities.GetEnumerator();
            Entities   = entities;
            FieldCount = Properties.Count;
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a SQL Statement for repository insert operation that is meant for SQL Server.
        /// </summary>
        /// <typeparam name="TEntity">
        /// The data entity object bound for the SQL Statement to be created.
        /// </typeparam>
        /// <param name="queryBuilder">An instance of query builder used to build the SQL statement.</param>
        /// <param name="isPrimaryIdentity">A boolean value indicates whether the primary key is identity in the database.</param>
        /// <returns>A string containing the composed SQL Statement for insert operation.</returns>
        internal string CreateInsert <TEntity>(QueryBuilder <TEntity> queryBuilder, bool?isPrimaryIdentity = null)
            where TEntity : class
        {
            var primary = PrimaryKeyCache.Get <TEntity>();
            var fields  = PropertyCache.Get <TEntity>(Command.Insert)
                          .Where(property => !(isPrimaryIdentity == true && property.IsPrimary() == true))
                          .Select(property => new Field(property.GetMappedName()));

            // Build the SQL Statement
            queryBuilder = queryBuilder ?? new QueryBuilder <TEntity>();
            queryBuilder
            .Clear()
            .Insert()
            .Into()
            .TableName()
            .OpenParen()
            .FieldsFrom(fields)
            .CloseParen()
            .Values()
            .OpenParen()
            .ParametersFrom(fields)
            .CloseParen()
            .End();
            var result = isPrimaryIdentity == true ? "SCOPE_IDENTITY()" : (primary != null) ? $"@{primary.GetMappedName()}" : "NULL";

            queryBuilder
            .Select()
            .WriteText(result)
            .As("[Result]")
            .End();

            // Return the query
            return(queryBuilder.GetString());
        }
Exemplo n.º 7
0
            /// <summary>
            ///
            /// </summary>
            /// <returns></returns>
            private static Func <TEntity, IEnumerable <PropertyValue> > GetFunc()
            {
                // Expressions
                var addMethod   = StaticType.PropertyValueList.GetMethod("Add", new[] { StaticType.PropertyValue });
                var obj         = Expression.Parameter(typeof(TEntity), "obj");
                var constructor = StaticType.PropertyValue.GetConstructor(new[]
                {
                    StaticType.String,
                    StaticType.Object,
                    StaticType.ClassProperty
                });

                // Set the body
                var properties = PropertyCache.Get <TEntity>();
                var body       = Expression.ListInit(
                    Expression.New(StaticType.PropertyValueList),
                    properties.Select(property =>
                {
                    var name          = Expression.Constant(property.GetMappedName());
                    var value         = Expression.Convert(Expression.Property(obj, property.PropertyInfo), StaticType.Object);
                    var propertyValue = Expression.New(constructor,
                                                       name,
                                                       value,
                                                       Expression.Constant(property));
                    return(Expression.ElementInit(addMethod, propertyValue));
                }));

                // Set the function value
                var lambdaExpr = Expression.Lambda <Func <TEntity, IEnumerable <PropertyValue> > >(body, obj);
                var lambda     = lambdaExpr
                                 .CompileFast();

                return(lambda);
            }
Exemplo n.º 8
0
        /// <summary>
        /// Appends a stringified fields to the SQL Query Statement.
        /// </summary>
        /// <typeparam name="TEntity">The type of data entity object bound for the SQL Statement to be created.</typeparam>
        /// <param name="dbSetting">The database setting that is currently in used.</param>
        /// <returns>The current instance.</returns>
        public QueryBuilder FieldsFrom <TEntity>(IDbSetting dbSetting)
            where TEntity : class
        {
            var fields = PropertyCache.Get <TEntity>(dbSetting)?.Select(property => property.GetUnquotedMappedName());

            return(Append(fields?.AsFields(dbSetting).Join(", ")));
        }
Exemplo n.º 9
0
        /// <summary>
        /// Gets the cached primary property of the data entity.
        /// </summary>
        /// <param name="entityType">The type of the data entity.</param>
        /// <returns>The cached primary property.</returns>
        public static ClassProperty Get(Type entityType)
        {
            // Variables for the cache
            var property = (ClassProperty)null;
            var key      = GenerateHashCode(entityType);

            // Try get the value
            if (m_cache.TryGetValue(key, out property) == false)
            {
                // Get all with IsPrimary() flags
                var properties = PropertyCache.Get(entityType).Where(p => p.IsPrimary() == true);

                // Check if there is forced [Primary] attribute
                property = properties.FirstOrDefault(p => p.GetPrimaryAttribute() != null);

                // Otherwise, get the first one
                if (property == null)
                {
                    property = properties?.FirstOrDefault();
                }

                // Add to the cache (whatever)
                m_cache.TryAdd(key, property);
            }

            // Return the value
            return(property);
        }
Exemplo n.º 10
0
        // Static Methods

        #region Parse (Expression)

        /// <summary>
        /// Parse an instance of <see cref="BinaryExpression"/> object.
        /// </summary>
        /// <typeparam name="TEntity">The target entity type</typeparam>
        /// <param name="expression">The instance of <see cref="BinaryExpression"/> to be parsed.</param>
        /// <returns>An instance of <see cref="QueryField"/> object.</returns>
        internal static QueryField Parse <TEntity>(BinaryExpression expression) where TEntity : class
        {
            // Only support the following expression type
            if (expression.IsExtractable() == false)
            {
                throw new NotSupportedException($"Expression '{expression.ToString()}' is currently not supported.");
            }

            // Name
            var fieldName = expression.GetName();

            if (PropertyCache.Get <TEntity>(Command.None).Any(property => property.PropertyInfo.Name == fieldName) == false)
            {
                throw new InvalidQueryExpressionException($"Invalid expression '{expression.ToString()}'. The property {fieldName} is not defined on a target type '{typeof(TEntity).FullName}'.");
            }

            // Value
            var value = expression.GetValue();

            // Operation
            var operation = GetOperation(expression.NodeType);

            // Return the value
            return(new QueryField(fieldName, operation, value));
        }
Exemplo n.º 11
0
        /// <summary>
        /// Gets the cached primary property of the data entity.
        /// </summary>
        /// <param name="type">The type of the target entity.</param>
        /// <param name="dbSetting">The database setting that is currently in used.</param>
        /// <returns>The cached primary property.</returns>
        public static ClassProperty Get(Type type,
                                        IDbSetting dbSetting)
        {
            // Variables for the cache
            var property = (ClassProperty)null;
            var key      = type.FullName.GetHashCode();

            // Add the DbSetting hashcode
            if (dbSetting != null)
            {
                key += dbSetting.GetHashCode();
            }

            // Try get the value
            if (m_cache.TryGetValue(key, out property) == false)
            {
                // Get all with IsPrimary() flags
                var properties = PropertyCache.Get(type, dbSetting).Where(p => p.IsPrimary() == true);

                // Check if there is forced [Primary] attribute
                property = properties.FirstOrDefault(p => p.GetPrimaryAttribute() != null);

                // Otherwise, get the first one
                if (property == null)
                {
                    property = properties?.FirstOrDefault();
                }

                // Add to the cache (whatever)
                m_cache.TryAdd(key, property);
            }

            // Return the value
            return(property);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Appends a stringified fields to the SQL Query Statement with aliases.
        /// </summary>
        /// <param name="alias">The alias to be prepended for each field.</param>
        /// <typeparam name="TEntity">The type of data entity object bound for the SQL Statement to be created.</typeparam>
        /// <returns>The current instance.</returns>
        public QueryBuilder AsAliasFieldsFrom <TEntity>(string alias)
            where TEntity : class
        {
            var fields = PropertyCache.Get <TEntity>()?.Select(property => property.GetUnquotedMappedName());

            return(Append(fields?.AsAliasFields(alias).Join(", ")));
        }
Exemplo n.º 13
0
        /// <summary>
        /// Creates a SQL Statement for repository update operation that is meant for SQL Server.
        /// </summary>
        /// <typeparam name="TEntity">
        /// The data entity object bound for the SQL Statement to be created.
        /// </typeparam>
        /// <param name="queryBuilder">An instance of query builder used to build the SQL statement.</param>
        /// <param name="where">The query expression for SQL statement.</param>
        /// <returns>A string containing the composed SQL Statement for update operation.</returns>
        public string CreateUpdate <TEntity>(QueryBuilder <TEntity> queryBuilder, QueryGroup where = null)
            where TEntity : class
        {
            var properties = PropertyCache.Get <TEntity>(Command.Update);

            if (properties?.Any() == false)
            {
                throw new InvalidOperationException($"No updateable fields found from type '{typeof(TEntity).FullName}'.");
            }
            var primary  = PrimaryKeyCache.Get <TEntity>();
            var identity = IdentityCache.Get <TEntity>();

            if (identity != null && identity != primary)
            {
                throw new InvalidOperationException($"Identity property must be the primary property for type '{typeof(TEntity).FullName}'.");
            }
            var fields = properties
                         .Where(property => property.IsPrimary() == false && property.IsIdentity() == false)
                         .Select(p => new Field(p.GetMappedName()));

            where?.AppendParametersPrefix();
            queryBuilder = queryBuilder ?? new QueryBuilder <TEntity>();
            queryBuilder
            .Clear()
            .Update()
            .TableName()
            .Set()
            .FieldsAndParametersFrom(fields)
            .WhereFrom(where)
            .End();
            return(queryBuilder.GetString());
        }
Exemplo n.º 14
0
 public static IEnumerable <PropertyValue> Do(TEntity obj)
 {
     if (m_func == null)
     {
         m_func = GetFunc(PropertyCache.Get <TEntity>());
     }
     return(m_func(obj));
 }
Exemplo n.º 15
0
        /// <summary>
        /// Append the stringified parameter as fields to the SQL Query Statement.
        /// </summary>
        /// <typeparam name="TEntity">The type of data entity object bound for the SQL Statement to be created.</typeparam>
        /// <param name="index">The parameter index.</param>
        /// <param name="dbSetting">The currently in used <see cref="IDbSetting"/> object.</param>
        /// <returns>The current instance.</returns>
        public QueryBuilder ParametersAsFieldsFrom <TEntity>(int index,
                                                             IDbSetting dbSetting)
            where TEntity : class
        {
            var fields = PropertyCache.Get <TEntity>()?.Select(property => property.GetMappedName()).AsFields();

            return(ParametersAsFieldsFrom(fields, index, dbSetting));
        }
Exemplo n.º 16
0
 /// <summary>
 ///
 /// </summary>
 /// <returns></returns>
 private IEnumerable <ClassProperty> GetClassProperties()
 {
     if (isDictionaryStringObject)
     {
         return(Enumerable.Empty <ClassProperty>());
     }
     return(PropertyCache.Get(EntityType)?.AsList());
 }
Exemplo n.º 17
0
 /// <summary>
 /// Parses an object and creates an enumerable of <see cref="Field"/> objects.
 /// </summary>
 /// <typeparam name="TEntity">The target type.</typeparam>
 /// <param name="entity">An object to be parsed.</param>
 /// <returns>An enumerable of <see cref="Field"/> objects.</returns>
 internal static IEnumerable <Field> Parse <TEntity>(TEntity entity)
     where TEntity : class
 {
     foreach (var property in PropertyCache.Get <TEntity>())
     {
         yield return(property.AsField());
     }
 }
Exemplo n.º 18
0
        /// <summary>
        /// Appends a stringified fields and parameters to the SQL Query Statement with aliases.
        /// </summary>
        /// <param name="alias">The alias to be prepended for each field.</param>
        /// <typeparam name="TEntity">The type of data entity object bound for the SQL Statement to be created.</typeparam>
        /// <param name="dbSetting">The currently in used <see cref="IDbSetting"/> object.</param>
        /// <returns>The current instance.</returns>
        public QueryBuilder FieldsAndAliasFieldsFrom <TEntity>(string alias,
                                                               IDbSetting dbSetting)
            where TEntity : class
        {
            var fields = PropertyCache.Get <TEntity>()?.Select(property => property.GetMappedName());

            return(Append(fields?.AsFieldsAndAliasFields(alias, dbSetting).Join(", ")));
        }
Exemplo n.º 19
0
        /// <summary>
        /// Creates a SQL Statement for repository batch query operation that is meant for SQL Server.
        /// </summary>
        /// <typeparam name="TEntity">
        /// The data entity object bound for the SQL Statement to be created.
        /// </typeparam>
        /// <param name="queryBuilder">An instance of query builder used to build the SQL statement.</param>
        /// <param name="where">The query expression for SQL statement.</param>
        /// <param name="page">The page of the batch.</param>
        /// <param name="rowsPerBatch">The number of rows per batch.</param>
        /// <param name="orderBy">The list of fields used for ordering.</param>
        /// <param name="hints">The hints to be used to optimze the query operation.</param>
        /// <returns>A string containing the composed SQL Statement for batch query operation.</returns>
        public string CreateBatchQuery <TEntity>(QueryBuilder <TEntity> queryBuilder,
                                                 QueryGroup where = null,
                                                 int?page         = null,
                                                 int?rowsPerBatch = null,
                                                 IEnumerable <OrderField> orderBy = null,
                                                 string hints = null)
            where TEntity : class
        {
            var fields = PropertyCache.Get <TEntity>().Select(property => new Field(property.GetMappedName()));

            // There should be fields
            if (fields == null || fields?.Any() == false)
            {
                throw new InvalidOperationException($"No batch queryable fields found from type '{typeof(TEntity).FullName}'.");
            }

            // Build the SQL Statement
            queryBuilder = queryBuilder ?? new QueryBuilder <TEntity>();
            queryBuilder
            .Clear()
            .With()
            .WriteText("CTE")
            .As()
            .OpenParen()
            .Select()
            .RowNumber()
            .Over()
            .OpenParen()
            .OrderByFrom(orderBy)
            .CloseParen()
            .As("[RowNumber],")
            .FieldsFrom(fields)
            .From()
            .TableName();

            // Build the query optimizers
            if (hints != null)
            {
                queryBuilder
                .WriteText(hints);
            }

            // Build the filter and ordering
            queryBuilder
            .WhereFrom(where)
            .CloseParen()
            .Select()
            .FieldsFrom(fields)
            .From()
            .WriteText("CTE")
            .WriteText(string.Concat("WHERE ([RowNumber] BETWEEN ", (page * rowsPerBatch) + 1, " AND ", (page + 1) * rowsPerBatch, ")"))
            .OrderByFrom(orderBy)
            .End();

            // Return the query
            return(queryBuilder.GetString());
        }
Exemplo n.º 20
0
        /// <summary>
        /// Gets the values of the property of the data entities (via property name).
        /// </summary>
        /// <typeparam name="TEntity">The type of the data entities.</typeparam>
        /// <typeparam name="TResult">The result type of the extracted property.</typeparam>
        /// <param name="entities">The list of the data entities.</param>
        /// <param name="propertyName">The name of the target property.</param>
        /// <returns>The values of the property of the data entities.</returns>
        public static IEnumerable <TResult> GetEntitiesPropertyValues <TEntity, TResult>(IEnumerable <TEntity> entities,
                                                                                         string propertyName)
            where TEntity : class
        {
            var classProperty = PropertyCache.Get <TEntity>()
                                .Where(p => string.Equals(p.PropertyInfo.Name, propertyName, StringComparison.OrdinalIgnoreCase))
                                .FirstOrDefault();

            return(GetEntitiesPropertyValues <TEntity, TResult>(entities, classProperty));
        }
Exemplo n.º 21
0
        /// <summary>
        /// Gets the values of the property of the data entities. The comparisson will be based on the mappings.
        /// </summary>
        /// <typeparam name="TEntity">The type of the data entities.</typeparam>
        /// <typeparam name="TResult">The result type of the extracted property.</typeparam>
        /// <param name="entities">The list of the data entities.</param>
        /// <param name="dbField">The name of the target property defined as <see cref="DbField"/>.</param>
        /// <returns>The values of the property of the data entities.</returns>
        public static IEnumerable <TResult> GetEntitiesPropertyValues <TEntity, TResult>(IEnumerable <TEntity> entities,
                                                                                         DbField dbField)
            where TEntity : class
        {
            var property = PropertyCache.Get <TEntity>()
                           .Where(e => string.Equals(e.GetMappedName(), dbField.Name))
                           .FirstOrDefault();

            return(GetEntitiesPropertyValues <TEntity, TResult>(entities, property));
        }
Exemplo n.º 22
0
        /// <summary>
        /// Gets the values of the property of the data entities.
        /// </summary>
        /// <typeparam name="TEntity">The type of the data entities.</typeparam>
        /// <typeparam name="TResult">The result type of the extracted property.</typeparam>
        /// <param name="entities">The list of the data entities.</param>
        /// <param name="propertyName">The name of the target property.</param>
        /// <returns>The values of the property of the data entities.</returns>
        public static IEnumerable <TResult> GetEntitiesPropertyValues <TEntity, TResult>(IEnumerable <TEntity> entities,
                                                                                         string propertyName)
            where TEntity : class
        {
            var property = PropertyCache.Get <TEntity>()
                           .Where(e => string.Equals(e.PropertyInfo.Name, propertyName))
                           .FirstOrDefault();

            return(GetEntitiesPropertyValues <TEntity, TResult>(entities, property));
        }
Exemplo n.º 23
0
        /// <summary>
        /// Gets the values of the property of the data entities (via expression).
        /// </summary>
        /// <typeparam name="TEntity">The type of the data entities.</typeparam>
        /// <typeparam name="TResult">The result type of the extracted property.</typeparam>
        /// <param name="entities">The list of the data entities.</param>
        /// <param name="expression">The expression to be parsed.</param>
        /// <returns>The values of the property of the data entities.</returns>
        public static IEnumerable <TResult> GetEntitiesPropertyValues <TEntity, TResult>(IEnumerable <TEntity> entities,
                                                                                         Expression <Func <TEntity, object> > expression)
            where TEntity : class
        {
            var property      = ExpressionExtension.GetProperty <TEntity>(expression);
            var propertyCache = PropertyCache.Get <TEntity>()
                                .Where(p => p.PropertyInfo == property || string.Equals(p.PropertyInfo.Name, property.Name, StringComparison.OrdinalIgnoreCase))
                                .FirstOrDefault();

            return(GetEntitiesPropertyValues <TEntity, TResult>(entities, propertyCache));
        }
Exemplo n.º 24
0
        /// <summary>
        /// Gets the cached identity key property for the entity.
        /// </summary>
        /// <typeparam name="TEntity">The type of the target entity.</typeparam>
        /// <returns>The cached identity property.</returns>
        public static ClassProperty Get <TEntity>()
            where TEntity : class
        {
            var key      = typeof(TEntity).FullName;
            var property = (ClassProperty)null;

            if (m_cache.TryGetValue(key, out property) == false)
            {
                property = PropertyCache.Get <TEntity>().FirstOrDefault(p => p.IsIdentity() == true);
                m_cache.TryAdd(key, property);
            }
            return(property);
        }
Exemplo n.º 25
0
        private static QueryGroup ParseContainsForArray <TEntity>(MethodCallExpression expression, bool isNot, bool isEqualsTo = true) where TEntity : class
        {
            // Return null if there is no any arguments
            if (expression.Arguments?.Any() == false)
            {
                return(null);
            }

            // Get the last arg
            var last = expression
                       .Arguments
                       .LastOrDefault();

            // Make sure the last arg is a member
            if (last == null || last?.IsMember() == false)
            {
                throw new NotSupportedException($"Expression '{expression.ToString()}' is currently not supported.");
            }

            // Make sure it is a property info
            var member = last.ToMember().Member;

            if (member.IsPropertyInfo() == false)
            {
                throw new NotSupportedException($"Expression '{expression.ToString()}' is currently not supported.");
            }

            // Get the property
            var property = member.ToPropertyInfo();

            // Make sure the property is in the entity
            if (PropertyCache.Get <TEntity>().FirstOrDefault(p => p.PropertyInfo == property) == null)
            {
                throw new InvalidQueryExpressionException($"Invalid expression '{expression.ToString()}'. The property {property.Name} is not defined on a target type '{typeof(TEntity).FullName}'.");
            }

            // Get the values
            var values = expression.Arguments.First().GetValue();

            // Add to query fields
            var operation  = isNot ? Operation.NotIn : Operation.In;
            var queryField = new QueryField(property.Name, operation, values);

            // Return the result
            var queryGroup = new QueryGroup(queryField.AsEnumerable());

            queryGroup.SetIsNot(isEqualsTo == false);
            return(queryGroup);
        }
Exemplo n.º 26
0
        /// <summary>
        /// Gets the cached identity property of the data entity.
        /// </summary>
        /// <param name="type">The type of the target entity.</param>
        /// <returns>The cached identity property.</returns>
        public static ClassProperty Get(Type type)
        {
            var key      = type.FullName.GetHashCode();
            var property = (ClassProperty)null;

            // Try get the value
            if (m_cache.TryGetValue(key, out property) == false)
            {
                property = PropertyCache.Get(type).FirstOrDefault(p => p.IsIdentity() == true);
                m_cache.TryAdd(key, property);
            }

            // Return the value
            return(property);
        }
Exemplo n.º 27
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="expression"></param>
        /// <param name="isNot"></param>
        /// <param name="isEqualsTo"></param>
        /// <returns></returns>
        private static QueryGroup ParseContainsOrStartsWithOrEndsWithForStringProperty <TEntity>(MethodCallExpression expression,
                                                                                                 bool isNot,
                                                                                                 bool isEqualsTo)
            where TEntity : class
        {
            // TODO: Refactor this

            // Return null if there is no any arguments
            if (expression.Arguments?.Any() != true)
            {
                return(null);
            }

            // Get the value arg
            var value = Convert.ToString(expression.Arguments.FirstOrDefault()?.GetValue());

            // Make sure it has a value
            if (string.IsNullOrWhiteSpace(value))
            {
                throw new NotSupportedException($"Expression '{expression.ToString()}' is currently not supported.");
            }

            // Make sure it is a property info
            var member = expression.Object.ToMember().Member;

            if (member.IsPropertyInfo() == false)
            {
                throw new NotSupportedException($"Expression '{expression.ToString()}' is currently not supported.");
            }

            // Get the property
            var property = member.ToPropertyInfo();

            // Make sure the property is in the entity
            if (PropertyCache.Get <TEntity>().FirstOrDefault(p => string.Equals(p.PropertyInfo.Name, property.Name, StringComparison.OrdinalIgnoreCase)) == null)
            {
                throw new InvalidExpressionException($"Invalid expression '{expression.ToString()}'. The property {property.Name} is not defined on a target type '{typeof(TEntity).FullName}'.");
            }

            // Add to query fields
            var operation  = (isNot == isEqualsTo) ? Operation.NotLike : Operation.Like;
            var queryField = new QueryField(PropertyMappedNameCache.Get(property),
                                            operation,
                                            ConvertToLikeableValue(expression.Method.Name, value));

            // Return the result
            return(new QueryGroup(queryField.AsEnumerable()));
        }
Exemplo n.º 28
0
 /// <summary>
 /// Parses a property from the data entity object based on the given <see cref="NewExpression"/> and converts the result
 /// to <see cref="Field"/> object.
 /// </summary>
 /// <typeparam name="TEntity">The type of the data entity that contains the property to be parsed.</typeparam>
 /// <param name="expression">The expression to be parsed.</param>
 /// <returns>An enumerable list of <see cref="Field"/> objects.</returns>
 internal static IEnumerable <Field> Parse <TEntity>(NewExpression expression)
     where TEntity : class
 {
     if (expression.Members?.Count >= 0)
     {
         var properties = expression
                          .Members
                          .WithType <PropertyInfo>();
         var classProperties = PropertyCache.Get <TEntity>()?
                               .Where(classProperty =>
                                      properties?.FirstOrDefault(property => string.Equals(property.Name, classProperty.PropertyInfo.Name, StringComparison.OrdinalIgnoreCase)) != null)
                               .Select(classProperty => classProperty.PropertyInfo);
         return((classProperties ?? properties).Select(property => property.AsField()));
     }
     return(null);
 }
Exemplo n.º 29
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="dbFields"></param>
 /// <returns></returns>
 private IEnumerable <ClassProperty> GetClassProperties(IEnumerable <DbField> dbFields)
 {
     if (isDictionaryStringObject)
     {
         return(Enumerable.Empty <ClassProperty>());
     }
     if (dbFields?.Any() == true)
     {
         return(PropertyCache.Get <TEntity>()?
                .Where(p => dbFields.FirstOrDefault(f => string.Equals(f.Name.AsQuoted(DbSetting), p.GetMappedName().AsQuoted(DbSetting), StringComparison.OrdinalIgnoreCase)) != null)
                .AsList());
     }
     else
     {
         return(PropertyCache.Get <TEntity>()?.AsList());
     }
 }
Exemplo n.º 30
0
        /// <summary>
        /// Property Level: Adds a property handler mapping into a <see cref="PropertyInfo"/> object.
        /// </summary>
        /// <typeparam name="TPropertyHandler">The type of the property handler.</typeparam>
        /// <param name="entityType">The target .NET CLR type.</param>
        /// <param name="propertyInfo">The instance of <see cref="PropertyInfo"/> to be mapped.</param>
        /// <param name="propertyHandler">The instance of the property handler.</param>
        /// <param name="force">A value that indicates whether to force the mapping. If one is already exists, then it will be overwritten.</param>
        internal static void Add <TPropertyHandler>(Type entityType,
                                                    PropertyInfo propertyInfo,
                                                    TPropertyHandler propertyHandler,
                                                    bool force)
        {
            // Validate
            ThrowNullReferenceException(propertyInfo, "PropertyInfo");
            ThrowNullReferenceException(propertyHandler, "PropertyHandler");
            Guard(propertyHandler?.GetType() ?? typeof(TPropertyHandler));

            /*
             * Note: The reflected type of the property info if explored via expression is different, therefore, we
             * need to manually extract it.
             */

            // Extract
            if (propertyInfo != null)
            {
                propertyInfo = PropertyCache.Get(entityType, propertyInfo.AsField()).PropertyInfo ?? propertyInfo;
            }

            // Variables
            var key   = GenerateHashCode(entityType, propertyInfo);
            var value = (object)null;

            // Try get the cache
            if (maps.TryGetValue(key, out value))
            {
                if (force)
                {
                    // Update the existing one
                    maps.TryUpdate(key, propertyHandler, value);
                }
                else
                {
                    // Throws an exception
                    throw new MappingExistsException($"A property handler mapping to '{propertyInfo.DeclaringType.FullName}.{propertyInfo.Name}' already exists.");
                }
            }
            else
            {
                // Add the mapping
                maps.TryAdd(key, propertyHandler);
            }
        }