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()); }
/// <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(", "))); }
/// <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)); }
/// <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); }
/// <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; }
/// <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()); }
/// <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); }
/// <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(", "))); }
/// <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); }
// 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)); }
/// <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); }
/// <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(", "))); }
/// <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()); }
public static IEnumerable <PropertyValue> Do(TEntity obj) { if (m_func == null) { m_func = GetFunc(PropertyCache.Get <TEntity>()); } return(m_func(obj)); }
/// <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)); }
/// <summary> /// /// </summary> /// <returns></returns> private IEnumerable <ClassProperty> GetClassProperties() { if (isDictionaryStringObject) { return(Enumerable.Empty <ClassProperty>()); } return(PropertyCache.Get(EntityType)?.AsList()); }
/// <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()); } }
/// <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(", "))); }
/// <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()); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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); }
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); }
/// <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); }
/// <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())); }
/// <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); }
/// <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()); } }
/// <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); } }