internal static bool ExecuteObjectExist(this DbHelper dbHelper, IRepositoryConventions conventions, DbCommand command, object obj) { Guard.NotNull(dbHelper, nameof(dbHelper)); Guard.NotNull(conventions, nameof(conventions)); Guard.NotNull(command, nameof(command)); Guard.NotNull(obj, nameof(obj)); var entityType = obj.GetType(); var tableName = conventions.GetTableName(entityType); var primaryKeyPropertyInfo = conventions.GetPrimaryKeyPropertyInfos(entityType).First(); var primaryKeyColumnName = conventions.GetColumnName(primaryKeyPropertyInfo); command.CommandText = $"SELECT * FROM [{tableName}]\nWHERE {primaryKeyColumnName} = @{primaryKeyColumnName}"; command.CommandType = CommandType.Text; command.Parameters.Clear(); command.AddParameter($"@{primaryKeyColumnName}", primaryKeyPropertyInfo.GetValue(obj, null)); var existInDb = false; using (var reader = dbHelper.ExecuteReader(command)) { while (reader.Read()) { existInDb = true; break; } } return(existInDb); }
/// <summary> /// Defaults this instance. /// </summary> /// <param name="conventions">The configurable conventions.</param> /// <returns>The default fetch strategy.</returns> public static IFetchQueryStrategy <T> Default([NotNull] IRepositoryConventions conventions) { Guard.NotNull(conventions, nameof(conventions)); var mainTableProperties = typeof(T).GetRuntimeProperties().ToList(); // Assumes we want to perform a join when the navigation property from the primary table has also a navigation property of // the same type as the primary table // Only do a join when the primary table has a foreign key property for the join table var paths = mainTableProperties .Where(x => x.IsComplex() && conventions.GetPrimaryKeyPropertyInfos(x.PropertyType).Any()) .Select(x => x.Name) .ToList(); var fetchStrategy = new FetchQueryStrategy <T>(); if (paths.Count > 0) { foreach (var path in paths) { fetchStrategy.Fetch(path); } } return(fetchStrategy); }
public static void CreateInsertStatement(IRepositoryConventions conventions, object entity, out string sql, out Dictionary <string, object> parameters) { Guard.NotNull(conventions, nameof(conventions)); Guard.NotNull(entity, nameof(entity)); parameters = new Dictionary <string, object>(); var entityType = entity.GetType(); var tableName = conventions.GetTableName(entityType); var primaryKeyPropertyInfos = conventions.GetPrimaryKeyPropertyInfos(entityType).ToList(); var properties = GetProperties(conventions, entityType); if (primaryKeyPropertyInfos.Count == 1) { var primaryKeyPropertyInfo = primaryKeyPropertyInfos.First(); var primaryKeyColumnName = conventions.GetColumnName(primaryKeyPropertyInfo); if (conventions.IsColumnIdentity(primaryKeyPropertyInfo)) { properties.Remove(primaryKeyColumnName); parameters.Add($"@{primaryKeyColumnName}", primaryKeyPropertyInfo.GetValue(entity, null)); } } foreach (var x in properties) { parameters.Add($"@{x.Key}", x.Value.GetValue(entity, null)); } var columnNames = string.Join(", ", properties.Select(x => x.Key)).TrimEnd(); var values = string.Join(", ", properties.Select(x => $"@{x.Key}")).TrimEnd(); sql = $"INSERT INTO [{tableName}] ({columnNames}){Environment.NewLine}VALUES ({values})"; }
/// <summary> /// Maps each element to a new form. /// </summary> /// <param name="reader">The data reader used for transforming each element.</param> /// <param name="conventions">The configurable conventions.</param> /// <returns>The new projected element form.</returns> public T Map([NotNull] IDataReader reader, [NotNull] IRepositoryConventions conventions) { Guard.NotNull(reader, nameof(reader)); Guard.NotNull(conventions, nameof(conventions)); var properties = GetProperties(conventions); var entity = Activator.CreateInstance <T>(); for (var i = 0; i < reader.FieldCount; i++) { var name = reader.GetName(i); var value = reader[name]; if (value == DBNull.Value) { value = null; } if (properties.ContainsKey(name)) { if (!reader.IsDBNull(reader.GetOrdinal(name))) { var pi = properties[name]; pi.SetValue(entity, value); } } } return(entity); }
public Customer Map(IDataReader reader, IRepositoryConventions conventions) { return(new Customer() { Id = reader.GetInt32(0), Name = reader.GetString(1) }); }
/// <summary> /// Returns the option instance with a configured conventions. /// </summary> /// <param name="conventions">The configurable conventions.</param> /// <returns>The same option instance.</returns> public RepositoryOptions With([NotNull] IRepositoryConventions conventions) { var clone = Clone(); clone._conventions = Guard.NotNull(conventions, nameof(conventions)); return(clone); }
/// <summary> /// Gets a collection of primary keys for the specified type. /// </summary> /// <param name="source">The repository conventions.</param> /// <param name="type">The type.</param> /// <returns>The collection of primary keys for the specified type.</returns> public static PropertyInfo[] GetPrimaryKeyPropertyInfos([NotNull] this IRepositoryConventions source, [NotNull] Type type) { Guard.NotNull(type, nameof(type)); var result = EnsureCallback( source.PrimaryKeysCallback, nameof(source.PrimaryKeysCallback))(type) ?? new PropertyInfo[0]; return(result); }
/// <summary> /// Initializes a new instance of the <see cref="RepositoryOptions" /> class. /// </summary> /// <param name="options">The repository options to clone.</param> public RepositoryOptions([NotNull] IRepositoryOptions options) { Guard.NotNull(options, nameof(options)); _interceptors = options.Interceptors.ToDictionary(x => x.Key, x => x.Value); _cachingProvider = options.CachingProvider; _loggerProvider = options.LoggerProvider; _contextFactory = options.ContextFactory; _conventions = options.Conventions; }
private static Dictionary <string, PropertyInfo> GetProperties(IRepositoryConventions conventions, Type entityType) { Guard.NotNull(conventions, nameof(conventions)); Guard.NotNull(entityType, nameof(entityType)); return(entityType .GetRuntimeProperties() .Where(x => x.IsPrimitive() && conventions.IsColumnMapped(x)) .OrderBy(conventions.GetColumnOrderOrDefault) .ToDictionary(conventions.GetColumnName, x => x)); }
public static void CreateSelectStatement <T>(IRepositoryConventions conventions, IQueryOptions <T> options, out string sql, out Dictionary <string, object> parameters) { CreateSelectStatement <T>( conventions, options, false, out sql, out parameters, out var navigationProperties, out var getPropertyFromColumnAliasCallback); }
public static void CreateSelectStatement <T>(IRepositoryConventions conventions, IQueryOptions <T> options, out string sql, out Dictionary <string, object> parameters, out Dictionary <Type, Dictionary <string, PropertyInfo> > navigationProperties, out Func <string, Type> getTableTypeByColumnAliasCallback) { CreateSelectStatement <T>( conventions, options, true, out sql, out parameters, out navigationProperties, out getTableTypeByColumnAliasCallback); }
/// <summary> /// Throws an exception if the specified entity type has an invalid primary key definition. /// </summary> /// <param name="source">The configurable conventions.</param> internal static void ThrowsIfInvalidPrimaryKeyDefinition <T>([NotNull] this IRepositoryConventions source) where T : class { var definedKeyInfos = source.GetPrimaryKeyPropertyInfos <T>(); if (!definedKeyInfos.Any()) { throw new InvalidOperationException(string.Format( Resources.EntityRequiresPrimaryKey, typeof(T).FullName)); } }
public Mapper(IRepositoryConventions conventions) { _conventions = Guard.NotNull(conventions, nameof(conventions)); _properties = typeof(T).GetRuntimeProperties() .Where(x => x.IsPrimitive() && _conventions.IsColumnMapped(x)) .OrderBy(_conventions.GetColumnOrderOrDefault) .ToDictionary(_conventions.GetColumnName, x => x); _navigationProperties = new Dictionary <Type, Dictionary <string, PropertyInfo> >(); }
public static bool IsColumnIdentity([NotNull] IRepositoryConventions conventions, [NotNull] PropertyInfo pi) { Guard.NotNull(pi, nameof(pi)); if (!_isColumnIdentityCache.TryGetValue(pi, out bool result)) { result = IsColumnIdentityCore(conventions, pi); _isColumnIdentityCache.TryAdd(pi, result); } return(result); }
private static bool IsColumnIdentityCore(IRepositoryConventions conventions, PropertyInfo pi) { var databaseGeneratedAttribute = pi.GetCustomAttribute <DatabaseGeneratedAttribute>(); if (databaseGeneratedAttribute == null) { var primaryKeyPropertyInfos = conventions.GetPrimaryKeyPropertyInfos(pi.DeclaringType); return((primaryKeyPropertyInfos.Length == 1) && primaryKeyPropertyInfos.First().Name.Equals(pi.Name)); } return(databaseGeneratedAttribute.DatabaseGeneratedOption == DatabaseGeneratedOption.Identity); }
public static int?GetColumnOrder([NotNull] IRepositoryConventions conventions, [NotNull] PropertyInfo pi) { Guard.NotNull(conventions, nameof(conventions)); Guard.NotNull(pi, nameof(pi)); if (!_columnOrderCache.TryGetValue(pi, out int?result)) { result = GetColumnOrderCore(conventions, pi); _columnOrderCache.TryAdd(pi, result); } return(result); }
private Dictionary <string, PropertyInfo> GetProperties([NotNull] IRepositoryConventions conventions) { Guard.NotNull(conventions, nameof(conventions)); if (_propertiesMapping == null || _propertiesMapping.Count == 0) { _propertiesMapping = typeof(T).GetRuntimeProperties() .Where(x => x.IsPrimitive() && conventions.IsColumnMapped(x)) .ToDictionary(conventions.GetColumnName, x => x); } return(_propertiesMapping); }
/// <summary> /// Gets a collection of primary keys for the specified type. /// </summary> /// <param name="source">The repository conventions.</param> /// <param name="type">The type.</param> /// <returns>The collection of primary keys for the specified type.</returns> public static PropertyInfo[] GetPrimaryKeyPropertyInfos([NotNull] this IRepositoryConventions source, [NotNull] Type type) { EnsureOwner(source); Guard.NotNull(type, nameof(type)); var store = _primaryKeyPropertyInfosCache.GetOrAdd(source.Owner, new ConcurrentDictionary <Type, PropertyInfo[]>()); if (!store.TryGetValue(type, out var result)) { store[type] = result = EnsureCallback( source.PrimaryKeysCallback, nameof(source.PrimaryKeysCallback))(type) ?? new PropertyInfo[0]; } return(result); }
private static Type EnsureOwner([NotNull] IRepositoryConventions source) { Guard.NotNull(source, nameof(source)); var owner = Guard.EnsureNotNull( source.Owner, string.Format("The conventions '{0}' cannot be null.", nameof(source.Owner))); if (!owner.ImplementsInterface(typeof(IRepositoryContext))) { throw new InvalidOperationException(string.Format( "The conventions '{0}' is not an instance of type '{1}'.", nameof(source.Owner), typeof(IRepositoryContext).FullName)); } return(owner); }
/// <summary> /// Determines whether the specified property is defined as identity. /// </summary> /// <param name="source">The configurable conventions.</param> /// <param name="pi">The property.</param> /// <returns><c>true</c> if column is defined as identity.; otherwise, <c>false</c>.</returns> public static bool IsColumnIdentity([NotNull] this IRepositoryConventions source, [NotNull] PropertyInfo pi) { EnsureOwner(source); Guard.NotNull(pi, nameof(pi)); var store = _isColumnIdentityCallback.GetOrAdd(source.Owner, new ConcurrentDictionary <PropertyInfo, bool>()); if (!store.TryGetValue(pi, out var result)) { store[pi] = result = EnsureCallback( source.IsColumnIdentityCallback, nameof(source.IsColumnIdentityCallback))(pi); } return(result); }
/// <summary> /// Gets a column order for the specified property. /// </summary> /// <param name="source">The configurable conventions.</param> /// <param name="pi">The property.</param> /// <returns>The column order for the specified property.</returns> public static int?GetColumnOrder([NotNull] this IRepositoryConventions source, [NotNull] PropertyInfo pi) { EnsureOwner(source); Guard.NotNull(pi, nameof(pi)); var store = _columnOrderCache.GetOrAdd(source.Owner, new ConcurrentDictionary <PropertyInfo, int?>()); if (!store.TryGetValue(pi, out var result)) { store[pi] = result = EnsureCallback( source.ColumnOrderCallback, nameof(source.ColumnOrderCallback))(pi); } return(result); }
/// <summary> /// Gets a table name for the specified type. /// </summary> /// <param name="source">The configurable conventions.</param> /// <param name="type">The type.</param> /// <returns>The table name for the specified type.</returns> public static string GetTableName([NotNull] this IRepositoryConventions source, [NotNull] Type type) { EnsureOwner(source); Guard.NotNull(type, nameof(type)); var store = _tableNameCache.GetOrAdd(source.Owner, new ConcurrentDictionary <Type, string>()); if (!store.TryGetValue(type, out var result)) { store[type] = result = EnsureCallback( source.TableNameCallback, nameof(source.TableNameCallback))(type); } return(result); }
/// <summary> /// Gets a collection of foreign key properties that matches the specified foreign type. /// </summary> /// <param name="source">The repository conventions.</param> /// <param name="sourceType">The source type.</param> /// <param name="foreignType">The foreign type to match.</param> /// <returns>The collection of foreign key properties that matches the specified foreign type.</returns> public static PropertyInfo[] GetForeignKeyPropertyInfos([NotNull] this IRepositoryConventions source, [NotNull] Type sourceType, [NotNull] Type foreignType) { EnsureOwner(source); Guard.NotNull(sourceType, nameof(sourceType)); Guard.NotNull(foreignType, nameof(foreignType)); var store = _foreignKeyPropertyInfosCache.GetOrAdd(source.Owner, new ConcurrentDictionary <Tuple <Type, Type>, PropertyInfo[]>()); var key = Tuple.Create(sourceType, foreignType); if (!store.TryGetValue(key, out var result)) { store[key] = result = EnsureCallback( source.ForeignKeysCallback, nameof(source.ForeignKeysCallback))(sourceType, foreignType) ?? new PropertyInfo[0]; } return(result); }
/// <summary> /// Throws an exception if the specified key type collection does not match the ones defined for the entity. /// </summary> /// <param name="source">The configurable conventions.</param> /// <param name="keyTypes">The key type collection to check against.</param> public static void ThrowsIfInvalidPrimaryKeyDefinition <T>([NotNull] this IRepositoryConventions source, [NotNull] params Type[] keyTypes) where T : class { Guard.NotNull(source, nameof(source)); Guard.NotEmpty(keyTypes, nameof(keyTypes)); var definedKeyInfos = source.GetPrimaryKeyPropertyInfos <T>().ToList(); if (!definedKeyInfos.Any()) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.EntityRequiresPrimaryKey, typeof(T).FullName)); } if (definedKeyInfos.Count > 1) { var hasNoKeyOrdering = definedKeyInfos.Any(x => { var columnOrdering = source.GetColumnOrder(x); if (!columnOrdering.HasValue) { return(true); } return(columnOrdering.Value <= 0); }); if (hasNoKeyOrdering) { throw new InvalidOperationException(string.Format( Resources.UnableToDetermineCompositePrimaryKeyOrdering, typeof(T).FullName)); } } var definedKeyTypes = definedKeyInfos .Select(x => x.PropertyType) .ToArray(); if (keyTypes.Length != definedKeyTypes.Length || definedKeyTypes.Where((t, i) => t != keyTypes[i]).Any()) { throw new InvalidOperationException(Resources.EntityPrimaryKeyTypesMismatch); } }
private static int?GetColumnOrderCore(IRepositoryConventions conventions, PropertyInfo pi) { var columnAttribute = pi.GetCustomAttribute <ColumnAttribute>(); if (columnAttribute == null) { // Checks to see if the property is a primary key, and if so, try to give it the lowest ordering number var primerKeyPropertyInfos = conventions.GetPrimaryKeyPropertyInfos(pi.DeclaringType); if ((primerKeyPropertyInfos.Length == 1) && primerKeyPropertyInfos.First().Name.Equals(pi.Name)) { return(-1); } } else if (columnAttribute.Order > 0) { return(columnAttribute.Order); } return(null); }
public static PropertyInfo[] GetPrimaryKeyPropertyInfos([NotNull] IRepositoryConventions conventions, [NotNull] Type entityType) { Guard.NotNull(conventions, nameof(conventions)); Guard.NotNull(entityType, nameof(entityType)); // Gets by checking the annotations var propertyInfos = entityType .GetRuntimeProperties() .Where(x => conventions.IsColumnMapped(x) && x.GetCustomAttribute <KeyAttribute>() != null) .OrderBy(x => { var columnAttribute = x.GetCustomAttribute <ColumnAttribute>(); if (columnAttribute != null && columnAttribute.Order > 0) { return(columnAttribute.Order); } return(int.MaxValue); }) .ToList(); // Gets by naming convention if (!propertyInfos.Any()) { foreach (var propertyName in GetDefaultPrimaryKeyNameChecks(entityType)) { var propertyInfo = entityType.GetTypeInfo().GetDeclaredProperty(propertyName); if (propertyInfo != null && conventions.IsColumnMapped(propertyInfo)) { propertyInfos.Add(propertyInfo); break; } } } return(propertyInfos.ToArray()); }
public static void CreateDeleteStatement(IRepositoryConventions conventions, object entity, out string sql, out Dictionary <string, object> parameters) { Guard.NotNull(conventions, nameof(conventions)); Guard.NotNull(entity, nameof(entity)); parameters = new Dictionary <string, object>(); var entityType = entity.GetType(); var tableName = conventions.GetTableName(entityType); var primaryKeyColumnNamesDict = conventions .GetPrimaryKeyPropertyInfos(entityType) .ToDictionary(conventions.GetColumnName, x => x); var condition = string.Join(" AND ", primaryKeyColumnNamesDict.Select(kv => "(" + kv.Key + " = @" + kv.Key + ")")); sql = $"DELETE FROM [{tableName}]{Environment.NewLine}WHERE ({condition})"; foreach (var x in primaryKeyColumnNamesDict) { parameters.Add($"@{x.Key}", x.Value.GetValue(entity, null)); } }
public static void CreateUpdateStatement(IRepositoryConventions conventions, object entity, out string sql, out Dictionary <string, object> parameters) { Guard.NotNull(conventions, nameof(conventions)); Guard.NotNull(entity, nameof(entity)); parameters = new Dictionary <string, object>(); var entityType = entity.GetType(); var tableName = conventions.GetTableName(entityType); var primaryKeyPropertyInfos = conventions.GetPrimaryKeyPropertyInfos(entityType).ToList(); var primaryKeyColumnNamesDict = primaryKeyPropertyInfos.ToDictionary(conventions.GetColumnName, x => x); var properties = GetProperties(conventions, entityType); if (primaryKeyPropertyInfos.Count == 1) { var primaryKeyPropertyInfo = primaryKeyPropertyInfos.First(); var primaryKeyColumnName = conventions.GetColumnName(primaryKeyPropertyInfo); if (conventions.IsColumnIdentity(primaryKeyPropertyInfo)) { properties.Remove(primaryKeyColumnName); parameters.Add($"@{primaryKeyColumnName}", primaryKeyPropertyInfo.GetValue(entity, null)); } } var values = string.Join($",{Environment.NewLine}\t", properties.Select(x => x.Key + " = " + $"@{x.Key}")); var condition = string.Join(" AND ", primaryKeyColumnNamesDict.Select(kv => "(" + kv.Key + " = @" + kv.Key + ")")); sql = $"UPDATE [{tableName}]{Environment.NewLine}SET {values}{Environment.NewLine}WHERE ({condition})"; foreach (var x in properties) { parameters.Add($"@{x.Key}", x.Value.GetValue(entity, null)); } }
/// <summary> /// Apply a sorting options to the specified entity's query. /// </summary> /// <returns>The entity's query with the applied options.</returns> public static IOrderedQueryable <T> ApplySortingOptions <T>([NotNull] this IQueryable <T> query, [NotNull] IRepositoryConventions conventions, [CanBeNull] IQueryOptions <T> options) where T : class { Guard.NotNull(query, nameof(query)); var sorting = new Dictionary <string, SortOrder>(); if (options != null) { sorting = options.SortingProperties.ToDictionary(x => x.Key, x => x.Value); } // Sorts on the composite key by default if no sorting is provided if (!sorting.Any()) { foreach (var primaryKeyPropertyInfo in conventions.GetPrimaryKeyPropertyInfos <T>()) { sorting.Add(primaryKeyPropertyInfo.Name, SortOrder.Ascending); } } var primarySorting = sorting.ElementAt(0); var primarySortingOrder = primarySorting.Value; var primarySortingProperty = primarySorting.Key; var sortedQuery = primarySortingOrder == SortOrder.Descending ? query.OrderByDescending(primarySortingProperty) : query.OrderBy(primarySortingProperty); for (var i = 1; i < sorting.Count; i++) { var sort = sorting.ElementAt(i); var sortOrder = sort.Value; var sortProperty = sort.Key; sortedQuery = sortOrder == SortOrder.Descending ? sortedQuery.ThenByDescending(sortProperty) : sortedQuery.ThenBy(sortProperty); } return(sortedQuery); }
public static IQueryable <T> ApplyFetchingOptions <T>(this IQueryable <T> query, IRepositoryConventions conventions, IQueryOptions <T> options) where T : class { Guard.NotNull(query, nameof(query)); var fetchingPaths = options.DefaultIfFetchStrategyEmpty(conventions).PropertyPaths.ToList(); if (fetchingPaths.Any()) { query = fetchingPaths.Aggregate(query, (current, path) => current.Include(path)); } return(query); }