From 77941c75eb36fea829d89818a45223567d5f23c4 Mon Sep 17 00:00:00 2001 From: Fereydoon Karimi Date: Sat, 21 Dec 2019 12:48:43 +0330 Subject: [PATCH 1/4] TableValuedFunction supporting was added. --- .editorconfig | 7 + Dapper.FastCrud.Tests/CrudSteps.cs | 2 +- Dapper.FastCrud.Tests/SqlBuilderSteps.cs | 4 +- .../Configuration/OrmConfiguration.cs | 19 +- ...tedRelationalSqlStatementOptionsBuilder.cs | 2 +- .../AggregatedSqlStatementOptionsBuilder.cs | 2 +- .../ISqlRelationOptionsSetter.cs | 2 +- .../IStandardSqlStatementOptionsSetter.cs | 2 +- .../Formatters/SqlParameterElementType.cs | 1 + .../Formatters/SqlParameterFormatter.cs | 4 +- .../Formatters/SqlStatementFormatter.cs | 4 +- .../Mappings/AutoGeneratedEntityMapping.cs | 21 +- Dapper.FastCrud/Mappings/EntityMapping.cs | 265 +++++++++++------- .../TableValuedFunctionEntityMapping.cs | 91 ++++++ Dapper.FastCrud/Sql.cs | 12 + Dapper.FastCrud/SqlBuilders/ISqlBuilder.cs | 13 +- .../SqlBuilders/StatementSqlBuilder.cs | 122 +++++--- .../RelationshipSqlStatements.cs | 4 +- 18 files changed, 406 insertions(+), 171 deletions(-) create mode 100644 .editorconfig create mode 100644 Dapper.FastCrud/Mappings/TableValuedFunctionEntityMapping.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..23d74fb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +# top-most EditorConfig file +root = true + +# Code files +[*] +indent_size = 4 +indent_style = space \ No newline at end of file diff --git a/Dapper.FastCrud.Tests/CrudSteps.cs b/Dapper.FastCrud.Tests/CrudSteps.cs index 20b05d0..7af8f9e 100644 --- a/Dapper.FastCrud.Tests/CrudSteps.cs +++ b/Dapper.FastCrud.Tests/CrudSteps.cs @@ -442,7 +442,7 @@ public void WhenIQueryForAMaximumOfWorkstationEntitiesInReverseOrderOfWorkstatio public void WhenIPartiallyUpdateAllTheInsertedEmployeeEntities() { // prepare a new mapping - var defaultMapping = OrmConfiguration.GetDefaultEntityMapping(); + var defaultMapping = OrmConfiguration.GetDefaultEntityMapping() as Mappings.EntityMapping; Assert.IsTrue(defaultMapping.IsFrozen); var lastNamePropMapping = defaultMapping.GetProperty(employee => employee.LastName); diff --git a/Dapper.FastCrud.Tests/SqlBuilderSteps.cs b/Dapper.FastCrud.Tests/SqlBuilderSteps.cs index f7651cf..8e7eaaa 100644 --- a/Dapper.FastCrud.Tests/SqlBuilderSteps.cs +++ b/Dapper.FastCrud.Tests/SqlBuilderSteps.cs @@ -81,9 +81,9 @@ public void ThenIShouldGetAValidJoinQueryStatementForWorkstation() { var buildingSqlBuilder = OrmConfiguration.GetSqlBuilder(); var expectedQuery = - $@" SELECT {_currentSqlBuilder.GetTableName()}.{_currentSqlBuilder.GetColumnName(nameof(Workstation.WorkstationId))}, {buildingSqlBuilder.GetTableName()}.{buildingSqlBuilder.GetColumnName(nameof(Building.BuildingId))} + $@" SELECT {_currentSqlBuilder.GetTableAliasName()}.{_currentSqlBuilder.GetColumnName(nameof(Workstation.WorkstationId))}, {buildingSqlBuilder.GetTableAliasName()}.{buildingSqlBuilder.GetColumnName(nameof(Building.BuildingId))} FROM {_currentSqlBuilder.GetTableName()}, {buildingSqlBuilder.GetTableName()} - WHERE {_currentSqlBuilder.GetTableName()}.{_currentSqlBuilder.GetColumnName(nameof(Workstation.BuildingId))} = {buildingSqlBuilder.GetTableName()}.{buildingSqlBuilder.GetColumnName(nameof(Building.BuildingId))}"; + WHERE {_currentSqlBuilder.GetTableAliasName()}.{_currentSqlBuilder.GetColumnName(nameof(Workstation.BuildingId))} = {buildingSqlBuilder.GetTableAliasName()}.{buildingSqlBuilder.GetColumnName(nameof(Building.BuildingId))}"; Assert.AreEqual(expectedQuery, _buildingRawJoinQueryStatement); } diff --git a/Dapper.FastCrud/Configuration/OrmConfiguration.cs b/Dapper.FastCrud/Configuration/OrmConfiguration.cs index f12026d..b0bee13 100644 --- a/Dapper.FastCrud/Configuration/OrmConfiguration.cs +++ b/Dapper.FastCrud/Configuration/OrmConfiguration.cs @@ -36,9 +36,9 @@ public static void ClearEntityRegistrations() /// Once the mappings have been used in query calls, the instance will be frozen and it won't support further modifications, but you can always call to create a new instance. /// /// Entity type - public static EntityMapping GetDefaultEntityMapping() + public static EntityMapping GetDefaultEntityMapping() { - return GetEntityDescriptor().DefaultEntityMapping as EntityMapping; + return GetEntityDescriptor().DefaultEntityMapping; } /// @@ -47,7 +47,16 @@ public static EntityMapping GetDefaultEntityMapping() /// Entity type public static EntityMapping RegisterEntity() { - return SetDefaultEntityMapping(new EntityMapping()); + return SetDefaultEntityMapping(new EntityMapping()) as EntityMapping; + } + + /// + /// Registers a new entity. Please continue setting up property mappings and other entity options with the returned default entity mapping instance. + /// + /// Entity type + public static TableValuedFunctionEntityMapping RegisterTableValuedFunctionEntity() + { + return SetDefaultEntityMapping(new TableValuedFunctionEntityMapping()) as TableValuedFunctionEntityMapping; } /// @@ -55,7 +64,7 @@ public static EntityMapping RegisterEntity() /// This must be called before any query operations were made on the entity. /// /// Entity type - public static EntityMapping SetDefaultEntityMapping(EntityMapping mappings) + public static EntityMapping SetDefaultEntityMapping(EntityMapping mappings) { Requires.NotNull(mappings, nameof(mappings)); Requires.Argument(!mappings.IsFrozen,nameof(mappings), "The entity mappings were frozen and can't be used as defaults. They must be cloned first."); @@ -70,7 +79,7 @@ public static EntityMapping SetDefaultEntityMapping(EntityMapp /// Entity type /// If NULL, de default entity mapping will be used. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ISqlBuilder GetSqlBuilder(EntityMapping entityMapping = null) + public static ISqlBuilder GetSqlBuilder(EntityMapping entityMapping = null) { return GetEntityDescriptor().GetSqlStatements(entityMapping).SqlBuilder; } diff --git a/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedRelationalSqlStatementOptionsBuilder.cs b/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedRelationalSqlStatementOptionsBuilder.cs index 4bef568..2d3801f 100644 --- a/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedRelationalSqlStatementOptionsBuilder.cs +++ b/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedRelationalSqlStatementOptionsBuilder.cs @@ -12,7 +12,7 @@ internal abstract class AggregatedRelationalSqlStatementOptionsBuilder /// Overrides the entity mapping for the current statement. /// - public TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping) + public TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping) { this.EntityMappingOverride = entityMapping; return this.Builder; diff --git a/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedSqlStatementOptionsBuilder.cs b/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedSqlStatementOptionsBuilder.cs index cde196a..e706483 100644 --- a/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedSqlStatementOptionsBuilder.cs +++ b/Dapper.FastCrud/Configuration/StatementOptions/Builders/Aggregated/AggregatedSqlStatementOptionsBuilder.cs @@ -90,7 +90,7 @@ public TStatementOptionsBuilder AttachToTransaction(IDbTransaction transaction) /// /// Overrides the entity mapping for the current statement. /// - public TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping) + public TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping) { this.EntityMappingOverride = entityMapping; return this.Builder; diff --git a/Dapper.FastCrud/Configuration/StatementOptions/ISqlRelationOptionsSetter.cs b/Dapper.FastCrud/Configuration/StatementOptions/ISqlRelationOptionsSetter.cs index 1d7ffc2..419f219 100644 --- a/Dapper.FastCrud/Configuration/StatementOptions/ISqlRelationOptionsSetter.cs +++ b/Dapper.FastCrud/Configuration/StatementOptions/ISqlRelationOptionsSetter.cs @@ -13,7 +13,7 @@ public interface ISqlRelationOptionsSetter /// Overrides the entity mapping for the current statement. /// - TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping); + TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping); /// /// Limits the result set with a where clause. diff --git a/Dapper.FastCrud/Configuration/StatementOptions/IStandardSqlStatementOptionsSetter.cs b/Dapper.FastCrud/Configuration/StatementOptions/IStandardSqlStatementOptionsSetter.cs index 6542b22..2bad0f0 100644 --- a/Dapper.FastCrud/Configuration/StatementOptions/IStandardSqlStatementOptionsSetter.cs +++ b/Dapper.FastCrud/Configuration/StatementOptions/IStandardSqlStatementOptionsSetter.cs @@ -22,6 +22,6 @@ public interface IStandardSqlStatementOptionsSetter /// Overrides the entity mapping for the current statement. /// - TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping); + TStatementOptionsBuilder WithEntityMappingOverride(EntityMapping entityMapping); } } diff --git a/Dapper.FastCrud/Formatters/SqlParameterElementType.cs b/Dapper.FastCrud/Formatters/SqlParameterElementType.cs index b8d3af1..84cdfcb 100644 --- a/Dapper.FastCrud/Formatters/SqlParameterElementType.cs +++ b/Dapper.FastCrud/Formatters/SqlParameterElementType.cs @@ -9,5 +9,6 @@ internal enum SqlParameterElementType Column, TableAndColumn, Identifier, + Function, } } diff --git a/Dapper.FastCrud/Formatters/SqlParameterFormatter.cs b/Dapper.FastCrud/Formatters/SqlParameterFormatter.cs index bd1e2ae..78d3282 100644 --- a/Dapper.FastCrud/Formatters/SqlParameterFormatter.cs +++ b/Dapper.FastCrud/Formatters/SqlParameterFormatter.cs @@ -115,9 +115,11 @@ public string ToString(string format, IFormatProvider formatProvider) case SqlParameterElementType.Table: return sqlBuilder.GetTableName(); case SqlParameterElementType.TableAndColumn: - return string.Format(CultureInfo.InvariantCulture,"{0}.{1}", sqlBuilder.GetTableName(), sqlBuilder.GetColumnName(this.ParameterValue)); + return string.Format(CultureInfo.InvariantCulture,"{0}.{1}", sqlBuilder.GetTableAliasName(), sqlBuilder.GetColumnName(this.ParameterValue)); case SqlParameterElementType.Identifier: return sqlBuilder.GetDelimitedIdentifier(this.ParameterValue); + case SqlParameterElementType.Function: + return sqlBuilder.GetFullFunctionCallClause(); default: throw new InvalidOperationException($"Unknown SQL element type {this.ElementType}"); } diff --git a/Dapper.FastCrud/Formatters/SqlStatementFormatter.cs b/Dapper.FastCrud/Formatters/SqlStatementFormatter.cs index 18923f9..85429e1 100644 --- a/Dapper.FastCrud/Formatters/SqlStatementFormatter.cs +++ b/Dapper.FastCrud/Formatters/SqlStatementFormatter.cs @@ -97,7 +97,7 @@ public string Format(string format, object arg, IFormatProvider formatProvider) return string.Format( CultureInfo.InvariantCulture, "{0}.{1}", - this.MainEntitySqlBuilder.GetTableName(), + this.MainEntitySqlBuilder.GetTableAliasName(), this.MainEntitySqlBuilder.GetColumnName(stringArg)); case "T": return this.MainEntitySqlBuilder.GetTableName(); @@ -105,6 +105,8 @@ public string Format(string format, object arg, IFormatProvider formatProvider) return this.MainEntitySqlBuilder.GetColumnName(stringArg); case "I": return this.MainEntitySqlBuilder.GetDelimitedIdentifier(stringArg); + case "F": + return this.MainEntitySqlBuilder.GetFullFunctionCallClause(); } } diff --git a/Dapper.FastCrud/Mappings/AutoGeneratedEntityMapping.cs b/Dapper.FastCrud/Mappings/AutoGeneratedEntityMapping.cs index 77eb8a8..c740f62 100644 --- a/Dapper.FastCrud/Mappings/AutoGeneratedEntityMapping.cs +++ b/Dapper.FastCrud/Mappings/AutoGeneratedEntityMapping.cs @@ -3,31 +3,14 @@ /// /// Discovers the orm mapping for a particular entity type. /// - internal class AutoGeneratedEntityMapping:EntityMapping + internal class AutoGeneratedEntityMapping : EntityMapping { /// /// Default constructor. /// public AutoGeneratedEntityMapping() { - var currentConventions = OrmConfiguration.Conventions; - - var tableName = currentConventions.GetTableName(this.EntityType); - this.SetTableName(tableName); - - var schemaName = currentConventions.GetSchemaName(this.EntityType); - { - if (!string.IsNullOrEmpty(schemaName)) - { - this.SetSchemaName(schemaName); - } - } - - foreach (var propDescriptor in currentConventions.GetEntityProperties(this.EntityType)) - { - var propMapping = this.SetPropertyInternal(propDescriptor); - currentConventions.ConfigureEntityPropertyMapping(propMapping); - } + base.InitializeEntityMapping(); } } } diff --git a/Dapper.FastCrud/Mappings/EntityMapping.cs b/Dapper.FastCrud/Mappings/EntityMapping.cs index 3aaadd4..771d899 100644 --- a/Dapper.FastCrud/Mappings/EntityMapping.cs +++ b/Dapper.FastCrud/Mappings/EntityMapping.cs @@ -1,16 +1,15 @@ -namespace Dapper.FastCrud.Mappings +using Dapper.FastCrud.Validations; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace Dapper.FastCrud.Mappings { - using System; - using System.Collections; - using System.Collections.Generic; - using System.ComponentModel; - using System.ComponentModel.DataAnnotations.Schema; - using System.Globalization; - using System.Linq; - using System.Linq.Expressions; - using System.Reflection; - using Dapper.FastCrud.Validations; - /// /// Holds information about table mapped properties for a particular entity type. /// Multiple instances of such mappings can be active for a single entity type. @@ -76,6 +75,49 @@ protected EntityMapping(Type entityType) /// internal IReadOnlyDictionary ParentChildRelationships => _parentChildRelationships; + /// + /// Returns property mapping information for a particular property. + /// + /// Name of the property (e.g. nameof(User.Name) ) + public PropertyMapping GetProperty(string propertyName) + { + PropertyMappings.TryGetValue(propertyName, out PropertyMapping propertyMapping); + return propertyMapping; + } + + /// + /// Returns all the property mappings, optionally filtered by their options. + /// + public PropertyMapping[] GetProperties(params PropertyMappingOptions[] includeFilter) + { + return this.PropertyMappings.Values + .Where(propInfo => (includeFilter.Length == 0 || includeFilter.Any(options => (options & propInfo.Options) == options))) + //.OrderBy(propInfo => propInfo.Order) + .ToArray(); + } + + /// + /// Returns all the property mappings, filtered by an exclusion filter. + /// + public PropertyMapping[] GetPropertiesExcluding(params string[] propNames) + { + return this.PropertyMappings.Values + .Where(propInfo => (propNames.Length == 0 || !propNames.Contains(propInfo.PropertyName))) + //.OrderBy(propInfo => propInfo.Order) + .ToArray(); + } + + /// + /// Returns all the property mappings, filtered by an exclusion filter. + /// + public PropertyMapping[] GetPropertiesExcluding(params PropertyMappingOptions[] excludeFilter) + { + return this.PropertyMappings.Values + .Where(propInfo => (excludeFilter.Length == 0 || excludeFilter.All(options => (options & propInfo.Options) != options))) + //.OrderBy(propInfo => propInfo.Order) + .ToArray(); + } + /// /// Freezes changes to the property mappings. /// @@ -143,7 +185,25 @@ internal void RemoveProperty(string propertyName) { throw new InvalidOperationException($"Failure removing property '{propertyName}'"); } - } + } + } + + /// + /// Sets the database table associated with your entity. + /// + /// Table name + protected void SetTableNameInternal(string tableName) + { + this.TableName = tableName; + } + + /// + /// Sets the database schema associated with your entity. + /// + /// Shema name + protected void SetSchemaNameInternal(string schemaName) + { + this.SchemaName = schemaName; } /// @@ -168,7 +228,7 @@ protected PropertyMapping SetPropertyInternal(PropertyDescriptor property) /// protected PropertyMapping SetPropertyInternal(PropertyMapping propertyMapping) { - Requires.Argument(propertyMapping.EntityMapping==this, nameof(propertyMapping), "Unable to add a property mapping that is not assigned to the current entity mapping"); + Requires.Argument(propertyMapping.EntityMapping == this, nameof(propertyMapping), "Unable to add a property mapping that is not assigned to the current entity mapping"); _propertyMappings.Remove(propertyMapping); _propertyMappings.Add(propertyMapping); _propertyNameMappingsMap[propertyMapping.PropertyName] = propertyMapping; @@ -179,7 +239,7 @@ protected PropertyMapping SetPropertyInternal(PropertyMapping propertyMapping) private void ConstructChildParentEntityRelationships() { _childParentRelationships = _propertyMappings - .Where(propertyMapping => propertyMapping.ChildParentRelationship!=null) + .Where(propertyMapping => propertyMapping.ChildParentRelationship != null) .GroupBy(propertyMapping => propertyMapping.ChildParentRelationship.ReferencedEntityType) .ToDictionary( groupedRelMappings => groupedRelMappings.Key, @@ -201,7 +261,7 @@ private void ConstructChildParentEntityRelationships() var prop = TypeDescriptor.GetProperties(this.EntityType).OfType().FirstOrDefault(x => x.Name == name); var attr = prop?.Attributes.OfType().FirstOrDefault(); - if (attr==null) + if (attr == null) { // Only add properties names which do not have NotMappedAttribute Set finalprops.Add(name); @@ -224,7 +284,7 @@ private void ConstructChildParentEntityRelationships() .SingleOrDefault(propDescriptor => propDescriptor.Name == referencingEntityPropertyName); - return new EntityMappingRelationship(groupedRelMappings.Key,groupedRelMappings.OrderBy(propMapping => propMapping.ColumnOrder).ToArray(), referencingEntityPropertyDescriptor); + return new EntityMappingRelationship(groupedRelMappings.Key, groupedRelMappings.OrderBy(propMapping => propMapping.ColumnOrder).ToArray(), referencingEntityPropertyDescriptor); }); } @@ -239,12 +299,12 @@ private void ConstructParentChildEntityRelationships() #else propDescriptor.PropertyType; #endif - return propInfo.IsGenericType - && typeof(IEnumerable).IsAssignableFrom(propDescriptor.PropertyType) - && propDescriptor.PropertyType.GetGenericArguments().Length == 1 - && !propDescriptor.Attributes.OfType().Any(); ; - }); - //.GroupBy(propDescriptor => propDescriptor.PropertyType) + return propInfo.IsGenericType + && typeof(IEnumerable).IsAssignableFrom(propDescriptor.PropertyType) + && propDescriptor.PropertyType.GetGenericArguments().Length == 1 + && !propDescriptor.Attributes.OfType().Any(); ; + }); + //.GroupBy(propDescriptor => propDescriptor.PropertyType) _parentChildRelationships = selectedProps.ToDictionary( propDescriptor => propDescriptor.PropertyType.GetGenericArguments()[0], propDescriptor => @@ -254,13 +314,37 @@ private void ConstructParentChildEntityRelationships() return new EntityMappingRelationship(propDescriptor.PropertyType, keyPropMappings, propDescriptor); }); } + + /// + /// Initialize the entity mapping by all properties and entity type. + /// + public virtual void InitializeEntityMapping() + { + var currentConventions = OrmConfiguration.Conventions; + + var tableName = currentConventions.GetTableName(this.EntityType); + this.SetTableNameInternal(tableName); + + var schemaName = currentConventions.GetSchemaName(this.EntityType); + if (!string.IsNullOrEmpty(schemaName)) + { + this.SetSchemaNameInternal(schemaName); + } + + + foreach (var propDescriptor in currentConventions.GetEntityProperties(this.EntityType)) + { + var propMapping = this.SetPropertyInternal(propDescriptor); + currentConventions.ConfigureEntityPropertyMapping(propMapping); + } + } } /// /// Holds information about table mapped properties for a particular entity type. /// Multiple instances of such mappings can be active for a single entity type. /// - public class EntityMapping : EntityMapping + public abstract class EntityMapping : EntityMapping { /// /// Default constructor. @@ -270,29 +354,34 @@ public EntityMapping() { } + /// + /// Current Entity Mapping + /// + protected abstract TEntityMapping CurrentEntityMapping { get; } + /// /// Sets the database table associated with your entity. /// /// Table name - public EntityMapping SetTableName(string tableName) + public TEntityMapping SetTableName(string tableName) { Requires.NotNullOrWhiteSpace(tableName, nameof(tableName)); this.ValidateState(); - this.TableName = tableName; - return this; + this.SetTableNameInternal(tableName); + return this.CurrentEntityMapping; } /// /// Sets the database schema associated with your entity. /// /// Shema name - public EntityMapping SetSchemaName(string schemaName) + public TEntityMapping SetSchemaName(string schemaName) { this.ValidateState(); - this.SchemaName = schemaName; - return this; + this.SetSchemaNameInternal(schemaName); + return this.CurrentEntityMapping; } /// @@ -300,19 +389,19 @@ public EntityMapping SetSchemaName(string schemaName) /// However, if plan on using the same dialect for all your db operations, it's best to use instead. /// /// Sql dialect - public EntityMapping SetDialect(SqlDialect dialect) + public TEntityMapping SetDialect(SqlDialect dialect) { this.ValidateState(); this.Dialect = dialect; - return this; + return this.CurrentEntityMapping; } /// /// Registers a regular property. /// /// Name of the property (e.g. user => user.LastName ) - public EntityMapping SetProperty(Expression> property) + public TEntityMapping SetProperty(Expression> property) { return this.SetProperty(property, (Action)null); } @@ -322,7 +411,7 @@ public EntityMapping SetProperty(Expression /// Name of the property (e.g. user => user.LastName ) /// A callback which will be called for setting up the property mapping. - public EntityMapping SetProperty( + public TEntityMapping SetProperty( Expression> property, Action propertySetupFct) { @@ -337,7 +426,7 @@ public EntityMapping SetProperty( { propertySetupFct(propMapping); } - return this; + return this.CurrentEntityMapping; } ///// @@ -347,7 +436,7 @@ public EntityMapping SetProperty( ///// Column options ///// Optional database column name override. //[Obsolete("This method is marked as obsolete and will be removed in future versions.")] - //public EntityMapping SetProperty( + //public TEntityMapping SetProperty( // Expression> property, // PropertyMappingOptions options, // string databaseColumnName = null) @@ -359,133 +448,89 @@ public EntityMapping SetProperty( //} /// - /// Returns all the property mappings, optionally filtered by their options. + /// Returns property mapping information for a particular property. /// - public PropertyMapping[] GetProperties(params PropertyMappingOptions[] includeFilter) + /// Name of the property (e.g. user => user.LastName ) + public PropertyMapping GetProperty(Expression> property) { - return this.PropertyMappings.Values - .Where(propInfo => (includeFilter.Length == 0 || includeFilter.Any(options => (options & propInfo.Options) == options))) - //.OrderBy(propInfo => propInfo.Order) - .ToArray(); + var propName = ((MemberExpression)property.Body).Member.Name; + return this.GetProperty(propName); } /// /// Gives an option for updating all the property mappings, optionally filtered by their options. /// - public EntityMapping UpdateProperties(Action updateFct, params PropertyMappingOptions[] includeFilter) + public TEntityMapping UpdateProperties(Action updateFct, params PropertyMappingOptions[] includeFilter) { foreach (var propMapping in this.GetProperties(includeFilter)) { updateFct(propMapping); } - return this; - } - - /// - /// Returns all the property mappings, filtered by an exclusion filter. - /// - public PropertyMapping[] GetPropertiesExcluding(params PropertyMappingOptions[] excludeFilter) - { - return this.PropertyMappings.Values - .Where(propInfo => (excludeFilter.Length==0 || excludeFilter.All(options => (options & propInfo.Options) != options))) - //.OrderBy(propInfo => propInfo.Order) - .ToArray(); + return this.CurrentEntityMapping; } /// /// Gives an option for updating all the property mappings, filtered by an exclusion filter. /// - public EntityMapping UpdatePropertiesExcluding(Action updateFct, params PropertyMappingOptions[] excludeFilter) + public TEntityMapping UpdatePropertiesExcluding(Action updateFct, params PropertyMappingOptions[] excludeFilter) { foreach (var propMapping in this.GetPropertiesExcluding(excludeFilter)) { updateFct(propMapping); } - return this; + return this.CurrentEntityMapping; } /// /// Returns all the property mappings, filtered by an exclusion filter. /// - public PropertyMapping[] GetPropertiesExcluding(params string[] propNames) - { - return this.PropertyMappings.Values - .Where(propInfo => (propNames.Length == 0 || !propNames.Contains(propInfo.PropertyName))) - //.OrderBy(propInfo => propInfo.Order) - .ToArray(); - } - - /// - /// Returns all the property mappings, filtered by an exclusion filter. - /// - public EntityMapping UpdatePropertiesExcluding(Action updateFct,params string[] propNames) + public TEntityMapping UpdatePropertiesExcluding(Action updateFct, params string[] propNames) { foreach (var propMapping in this.GetPropertiesExcluding(propNames)) { updateFct(propMapping); } - return this; - } - - /// - /// Returns property mapping information for a particular property. - /// - /// Name of the property (e.g. user => user.LastName ) - public PropertyMapping GetProperty(Expression> property) - { - var propName = ((MemberExpression)property.Body).Member.Name; - return this.GetProperty(propName); - } - - /// - /// Returns property mapping information for a particular property. - /// - /// Name of the property (e.g. nameof(User.Name) ) - public PropertyMapping GetProperty(string propertyName) - { - PropertyMapping propertyMapping = null; - PropertyMappings.TryGetValue(propertyName, out propertyMapping); - return propertyMapping; + return this.CurrentEntityMapping; } /// /// Removes the mapping for a property. /// /// Name of the property (e.g. user => user.LastName ) - public EntityMapping RemoveProperty(Expression> property) + public TEntityMapping RemoveProperty(Expression> property) { this.ValidateState(); var propName = ((MemberExpression)property.Body).Member.Name; - this.RemoveProperties(new [] { propName}, false); - return this; + this.RemoveProperties(new[] { propName }, false); + return this.CurrentEntityMapping; } /// /// Removes the mapping for a property. /// /// Name of the property (e.g. nameof(User.Name) ) - public EntityMapping RemoveProperty(params string[] propertyName) + public TEntityMapping RemoveProperty(params string[] propertyName) { this.ValidateState(); this.RemoveProperties(propertyName, false); - return this; + return this.CurrentEntityMapping; } /// /// Removes all the property mappings with the exception of the provided list. /// /// Name of the property (e.g. nameof(User.Name) ) - public EntityMapping RemoveAllPropertiesExcluding(params string[] propertyName) + public TEntityMapping RemoveAllPropertiesExcluding(params string[] propertyName) { this.ValidateState(); this.RemoveProperties(propertyName, true); - return this; + return this.CurrentEntityMapping; } ///// @@ -495,7 +540,7 @@ public EntityMapping RemoveAllPropertiesExcluding(params string[] prope ///// Column options ///// Optional database column name override. //[Obsolete("This method is marked as obsolete and will be removed in future versions.")] - //public EntityMapping SetProperty(string propertyName, PropertyMappingOptions options, string databaseColumnName = null) + //public TEntityMapping SetProperty(string propertyName, PropertyMappingOptions options, string databaseColumnName = null) //{ // this.ValidateState(); // Requires.NotNull(propertyName, nameof(propertyName)); @@ -525,18 +570,36 @@ public EntityMapping RemoveAllPropertiesExcluding(params string[] prope // { // throw new NotSupportedException("It is not possible to set up foreign keys via this method."); // } - // return this; + // return this.CurrentEntityMapping; //} /// /// Clones the current mapping set, allowing for further modifications. /// - public EntityMapping Clone() + public abstract TEntityMapping Clone(); + } + + /// + /// Holds information about table mapped properties for a particular entity type. + /// Multiple instances of such mappings can be active for a single entity type. + /// + public class EntityMapping : EntityMapping> + { + /// + /// Current Entity Mapping + /// + protected override EntityMapping CurrentEntityMapping => this; + + /// + /// Clones the current mapping set, allowing for further modifications. + /// + public override EntityMapping Clone() { var clonedMappings = new EntityMapping() .SetSchemaName(this.SchemaName) .SetTableName(this.TableName) .SetDialect(this.Dialect); + foreach (var clonedPropMapping in this.PropertyMappings.Select(propNameMapping => propNameMapping.Value.Clone(clonedMappings))) { clonedMappings.SetPropertyInternal(clonedPropMapping); diff --git a/Dapper.FastCrud/Mappings/TableValuedFunctionEntityMapping.cs b/Dapper.FastCrud/Mappings/TableValuedFunctionEntityMapping.cs new file mode 100644 index 0000000..6890bf0 --- /dev/null +++ b/Dapper.FastCrud/Mappings/TableValuedFunctionEntityMapping.cs @@ -0,0 +1,91 @@ +using Dapper.FastCrud.Validations; +using System.Collections.Generic; +using System.Linq; + +namespace Dapper.FastCrud.Mappings +{ + /// + /// Holds information about table-valued fanction mapped properties for a particular entity type. + /// Multiple instances of such mappings can be active for a single entity type. + /// + public interface ITableValuedFunctionEntityMapping + { + /// + /// table-valued function parameters + /// + IEnumerable ParameterNames { get; } + + /// + /// Constructs a parameter selection of all parameter to be refreshed function call of the form @PropertyName1,@PropertyName2... + /// + string ConstructFunctionParameterClause(); + } + + /// + /// Holds information about table-valued fanction mapped properties for a particular entity type. + /// Multiple instances of such mappings can be active for a single entity type. + /// + public sealed class TableValuedFunctionEntityMapping : EntityMapping>, ITableValuedFunctionEntityMapping + { + /// + /// table-valued function parameters + /// + public IEnumerable ParameterNames { get; private set; } + + /// + /// Default constructor. + /// + public TableValuedFunctionEntityMapping() + { + this.ParameterNames = new string[0]; + } + + /// + /// Current Entity Mapping + /// + protected override TableValuedFunctionEntityMapping CurrentEntityMapping => this; + + /// + /// Sets the database table-valued function parameters + /// + /// Parameters of table-valued functio name + public TableValuedFunctionEntityMapping SetFunctionParameterNames(string[] functionParameterNames) + { + this.ValidateState(); + + Requires.NotNull(functionParameterNames, nameof(functionParameterNames)); + + this.ParameterNames = functionParameterNames ?? new string[0]; + return this.CurrentEntityMapping; + } + + /// + /// Clones the current mapping set, allowing for further modifications. + /// + public override TableValuedFunctionEntityMapping Clone() + { + var clonedMappings = new TableValuedFunctionEntityMapping() + .SetSchemaName(this.SchemaName) + .SetTableName(this.TableName) + .SetFunctionParameterNames(this.ParameterNames.ToArray()) + .SetDialect(this.Dialect); + + foreach (var clonedPropMapping in this.PropertyMappings.Select(propNameMapping => propNameMapping.Value.Clone(clonedMappings))) + { + clonedMappings.SetPropertyInternal(clonedPropMapping); + } + + return clonedMappings; + } + + /// + /// Constructs a parameter selection of all parameter to be refreshed function call of the form @PropertyName1,@PropertyName2... + /// + string ITableValuedFunctionEntityMapping.ConstructFunctionParameterClause() + { + var parameterPrefix = OrmConfiguration.Conventions.GetDatabaseOptions(this.Dialect).ParameterPrefix; + return string.Join(",", this.ParameterNames.Select(parameterName => parameterPrefix + parameterName)); + + } + } +} diff --git a/Dapper.FastCrud/Sql.cs b/Dapper.FastCrud/Sql.cs index fbd3799..7a54b04 100644 --- a/Dapper.FastCrud/Sql.cs +++ b/Dapper.FastCrud/Sql.cs @@ -23,6 +23,18 @@ public static IFormattable Identifier(string sqlIdentifier) return new SqlParameterFormatter(SqlParameterElementType.Identifier, sqlIdentifier, null); } + /// + /// Returns a parameter formatter for an SQL function, allowing it to be properly formatted by adding delimiters. + /// Do not use this method for table or column names. + /// + /// An SQL identifier that is not a table or a column name. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IFormattable Function(string sqlFunction) + { + Requires.NotNullOrEmpty(sqlFunction, nameof(sqlFunction)); + return new SqlParameterFormatter(SqlParameterElementType.Function, sqlFunction, null); + } + /// /// Returns a parameter formatter for the SQL table name of the main entity. /// If you wish to resolve the table name of another entity, please use the generic overload instead. diff --git a/Dapper.FastCrud/SqlBuilders/ISqlBuilder.cs b/Dapper.FastCrud/SqlBuilders/ISqlBuilder.cs index 72ed5f9..1434be2 100644 --- a/Dapper.FastCrud/SqlBuilders/ISqlBuilder.cs +++ b/Dapper.FastCrud/SqlBuilders/ISqlBuilder.cs @@ -21,6 +21,17 @@ public interface ISqlBuilder /// Optional table alias using AS. string GetTableName(string tableAlias = null); + /// + /// Returns a table alias name generated by table name. + /// + string GetTableAliasName(); + + /// + /// Returns the table-valued function name associated with the current entity. + /// + /// Optional table alias using AS. + string GetFullFunctionCallClause(string tableAlias = null); + /// /// Returns the name of the database column attached to the specified property. /// Please use nameof(entity.propname) if available, alternatively use the other overload for this method. @@ -42,7 +53,7 @@ public interface ISqlBuilder /// /// Property for which you want to get the column name. /// Optional table alias. - string GetColumnName(Expression> property, string tableAlias = null); + string GetColumnName(Expression> property, string tableAlias = null); /// /// Constructs a condition of form ColumnName=@PropertyName and ... with all the key columns (e.g. Id=@Id and EmployeeId=@EmployeeId) diff --git a/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs b/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs index db6e2f1..acc9677 100644 --- a/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs +++ b/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs @@ -1,27 +1,29 @@ namespace Dapper.FastCrud.SqlBuilders { + using Dapper.FastCrud.Configuration.StatementOptions; + using Dapper.FastCrud.EntityDescriptors; + using Dapper.FastCrud.Formatters; + using Dapper.FastCrud.Mappings; + using Dapper.FastCrud.Validations; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Linq.Expressions; + using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; - using Dapper.FastCrud.Configuration.StatementOptions; - using Dapper.FastCrud.EntityDescriptors; - using Dapper.FastCrud.Formatters; - using Dapper.FastCrud.Mappings; - using Dapper.FastCrud.Validations; - using System.Reflection; - internal abstract class GenericStatementSqlBuilder:ISqlBuilder + internal abstract class GenericStatementSqlBuilder : ISqlBuilder { //private static readonly RelationshipOrderComparer _relationshipOrderComparer = new RelationshipOrderComparer(); //private readonly ConcurrentDictionary _entityRelationships; private readonly Lazy _noAliasKeysWhereClause; private readonly Lazy _noAliasTableName; + private readonly Lazy _noAliasFullFunctionCallClause; + private readonly Lazy _autoGeneratedTableAliasName; private readonly Lazy _noAliasKeyColumnEnumeration; private readonly Lazy _noAliasColumnEnumerationForSelect; private readonly Lazy _columnEnumerationForInsert; @@ -84,23 +86,24 @@ protected GenericStatementSqlBuilder( .Where(propInfo => !propInfo.IsExcludedFromInserts) .ToArray(); - _noAliasTableName = new Lazy(()=>this.GetTableNameInternal(),LazyThreadSafetyMode.PublicationOnly); - _noAliasKeysWhereClause = new Lazy(()=>this.ConstructKeysWhereClauseInternal(), LazyThreadSafetyMode.PublicationOnly); + _noAliasTableName = new Lazy(() => this.GetTableNameInternal(), LazyThreadSafetyMode.PublicationOnly); + _noAliasFullFunctionCallClause = new Lazy(() => this.GetFullFunctionCallClauseInternal(), LazyThreadSafetyMode.PublicationOnly); + _autoGeneratedTableAliasName = new Lazy(() => this.GetTableAliasNameInternal(), LazyThreadSafetyMode.PublicationOnly); + _noAliasKeysWhereClause = new Lazy(() => this.ConstructKeysWhereClauseInternal(), LazyThreadSafetyMode.PublicationOnly); _noAliasKeyColumnEnumeration = new Lazy(() => this.ConstructKeyColumnEnumerationInternal(), LazyThreadSafetyMode.PublicationOnly); _noAliasColumnEnumerationForSelect = new Lazy(() => this.ConstructColumnEnumerationForSelectInternal(), LazyThreadSafetyMode.PublicationOnly); - _columnEnumerationForInsert = new Lazy(()=>this.ConstructColumnEnumerationForInsertInternal(), LazyThreadSafetyMode.PublicationOnly); - _paramEnumerationForInsert = new Lazy(()=>this.ConstructParamEnumerationForInsertInternal(),LazyThreadSafetyMode.PublicationOnly); - _noAliasUpdateClause = new Lazy(()=>this.ConstructUpdateClauseInternal(),LazyThreadSafetyMode.PublicationOnly); - _fullInsertStatement = new Lazy(()=>this.ConstructFullInsertStatementInternal(),LazyThreadSafetyMode.PublicationOnly); - _fullSingleUpdateStatement = new Lazy(()=>this.ConstructFullSingleUpdateStatementInternal(),LazyThreadSafetyMode.PublicationOnly); - _noConditionFullBatchUpdateStatement = new Lazy(()=>this.ConstructFullBatchUpdateStatementInternal(),LazyThreadSafetyMode.PublicationOnly); - _fullSingleDeleteStatement = new Lazy(()=>this.ConstructFullSingleDeleteStatementInternal(),LazyThreadSafetyMode.PublicationOnly); - _noConditionFullBatchDeleteStatement = new Lazy(()=>this.ConstructFullBatchDeleteStatementInternal(),LazyThreadSafetyMode.PublicationOnly); - _noConditionFullCountStatement = new Lazy(()=>this.ConstructFullCountStatementInternal(),LazyThreadSafetyMode.PublicationOnly); - _fullSingleSelectStatement = new Lazy(()=>this.ConstructFullSingleSelectStatementInternal(),LazyThreadSafetyMode.PublicationOnly); + _columnEnumerationForInsert = new Lazy(() => this.ConstructColumnEnumerationForInsertInternal(), LazyThreadSafetyMode.PublicationOnly); + _paramEnumerationForInsert = new Lazy(() => this.ConstructParamEnumerationForInsertInternal(), LazyThreadSafetyMode.PublicationOnly); + _noAliasUpdateClause = new Lazy(() => this.ConstructUpdateClauseInternal(), LazyThreadSafetyMode.PublicationOnly); + _fullInsertStatement = new Lazy(() => this.ConstructFullInsertStatementInternal(), LazyThreadSafetyMode.PublicationOnly); + _fullSingleUpdateStatement = new Lazy(() => this.ConstructFullSingleUpdateStatementInternal(), LazyThreadSafetyMode.PublicationOnly); + _noConditionFullBatchUpdateStatement = new Lazy(() => this.ConstructFullBatchUpdateStatementInternal(), LazyThreadSafetyMode.PublicationOnly); + _fullSingleDeleteStatement = new Lazy(() => this.ConstructFullSingleDeleteStatementInternal(), LazyThreadSafetyMode.PublicationOnly); + _noConditionFullBatchDeleteStatement = new Lazy(() => this.ConstructFullBatchDeleteStatementInternal(), LazyThreadSafetyMode.PublicationOnly); + _noConditionFullCountStatement = new Lazy(() => this.ConstructFullCountStatementInternal(), LazyThreadSafetyMode.PublicationOnly); + _fullSingleSelectStatement = new Lazy(() => this.ConstructFullSingleSelectStatementInternal(), LazyThreadSafetyMode.PublicationOnly); } - public EntityDescriptor EntityDescriptor { get; } public EntityMapping EntityMapping { get; } public PropertyMapping[] SelectProperties { get; } @@ -127,6 +130,24 @@ public string GetTableName(string tableAlias = null) return tableAlias == null ? _noAliasTableName.Value : this.GetTableNameInternal(tableAlias); } + /// + /// Returns a table alias name generated by table name. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string GetTableAliasName() + { + return _autoGeneratedTableAliasName.Value; + } + + /// + /// Returns the table name associated with the current entity. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string GetFullFunctionCallClause(string tableAlias = null) + { + return tableAlias == null ? _noAliasFullFunctionCallClause.Value : this.GetFullFunctionCallClauseInternal(tableAlias); + } + /// /// Returns the name of the database column attached to the specified property. /// @@ -384,7 +405,7 @@ public void ConstructFullJoinSelectStatement( long? limitRowsCount = null) { Requires.NotNull(joinInstructions, nameof(joinInstructions)); - var allSqlJoinInstructions = new[] { new StatementSqlBuilderJoinInstruction(this, SqlJoinType.LeftOuterJoin, whereClause, orderClause) }.Concat(joinInstructions).ToArray(); + var allSqlJoinInstructions = new[] { new StatementSqlBuilderJoinInstruction(this, SqlJoinType.LeftOuterJoin, whereClause, orderClause) }.Concat(joinInstructions).ToArray(); Requires.Argument(allSqlJoinInstructions.Length > 1, nameof(joinInstructions), "Unable to create a full JOIN statement when no extra SQL builders were provided"); var selectClauseBuilder = selectClause == null ? new StringBuilder() : null; @@ -395,10 +416,11 @@ public void ConstructFullJoinSelectStatement( var joinClauseBuilder = new StringBuilder(); // enumerate through the join instructions and construct FIRST ENTITY - SECOND ENTITY joins - for(var secondEntityJoinInstructionIndex = 0; secondEntityJoinInstructionIndex < allSqlJoinInstructions.Length; secondEntityJoinInstructionIndex++) + for (var secondEntityJoinInstructionIndex = 0; secondEntityJoinInstructionIndex < allSqlJoinInstructions.Length; secondEntityJoinInstructionIndex++) { var secondEntityJoinSqlInstruction = allSqlJoinInstructions[secondEntityJoinInstructionIndex]; var secondEntitySqlBuilder = secondEntityJoinSqlInstruction.SqlBuilder; + var secondEntityTableAlias = secondEntitySqlBuilder.GetTableAliasName(); // prepare the aditional where clause var joinInstructionAdditionalWhereClause = secondEntityJoinSqlInstruction.WhereClause; @@ -434,7 +456,7 @@ public void ConstructFullJoinSelectStatement( selectClauseBuilder.Append(','); } - selectClauseBuilder.Append(secondEntitySqlBuilder.ConstructColumnEnumerationForSelect(secondEntitySqlBuilder.GetTableName())); + selectClauseBuilder.Append(secondEntitySqlBuilder.ConstructColumnEnumerationForSelect(secondEntityTableAlias)); } // add the split on expression @@ -451,7 +473,7 @@ public void ConstructFullJoinSelectStatement( // build the join expression if (secondEntityJoinInstructionIndex == 0) { - fromClauseBuilder.Append(secondEntitySqlBuilder.GetTableName()); + fromClauseBuilder.Append(secondEntitySqlBuilder.GetTableName(secondEntityTableAlias)); } else { @@ -481,7 +503,7 @@ public void ConstructFullJoinSelectStatement( atLeastOneRelationshipDiscovered = true; joinClauseBuilder.Append('('); - for (var firstEntityPropertyIndex = 0; firstEntityPropertyIndex 0) { @@ -489,13 +511,14 @@ public void ConstructFullJoinSelectStatement( } var firstEntityProperty = firstEntityPropertyMappings[firstEntityPropertyIndex]; - joinClauseBuilder.Append(firstEntitySqlBuilder.GetColumnName(firstEntityProperty, firstEntitySqlBuilder.GetTableName(), false)); + string firstEntityTableAlias = firstEntitySqlBuilder.GetTableAliasName(); + joinClauseBuilder.Append(firstEntitySqlBuilder.GetColumnName(firstEntityProperty, firstEntityTableAlias, false)); joinClauseBuilder.Append('='); // search for the corresponding column in the current entity // we're doing this by index, since both sides had the relationship columns already ordered var secondEntityProperty = secondEntityPropertyMappings[firstEntityPropertyIndex]; - joinClauseBuilder.Append(secondEntitySqlBuilder.GetColumnName(secondEntityProperty, secondEntitySqlBuilder.GetTableName(), false)); + joinClauseBuilder.Append(secondEntitySqlBuilder.GetColumnName(secondEntityProperty, secondEntityTableAlias, false)); } joinClauseBuilder.Append(')'); } @@ -519,7 +542,7 @@ public void ConstructFullJoinSelectStatement( throw new NotSupportedException($"Join '{secondEntityFinalJoinType}' is not supported"); } - fromClauseBuilder.Append(secondEntitySqlBuilder.GetTableName()); + fromClauseBuilder.Append(secondEntitySqlBuilder.GetTableName(secondEntityTableAlias)); fromClauseBuilder.Append(" ON "); fromClauseBuilder.Append(joinClauseBuilder.ToString()); } @@ -561,18 +584,49 @@ protected virtual string GetTableNameInternal(string tableAlias = null) : $" AS {this.GetDelimitedIdentifier(tableAlias)}"; FormattableString fullTableName; + string tableName = this.EntityMapping.TableName; if ((!this.UsesSchemaForTableNames) || string.IsNullOrEmpty(this.EntityMapping.SchemaName)) { - fullTableName = $"{this.GetDelimitedIdentifier(this.EntityMapping.TableName)}"; - } + fullTableName = $"{this.GetDelimitedIdentifier(tableName)}"; + } else { - fullTableName = $"{this.GetDelimitedIdentifier(this.EntityMapping.SchemaName)}.{this.GetDelimitedIdentifier(this.EntityMapping.TableName)}"; + fullTableName = $"{this.GetDelimitedIdentifier(EntityMapping.SchemaName)}.{this.GetDelimitedIdentifier(tableName)}"; + } + + if (this.EntityMapping is ITableValuedFunctionEntityMapping tableValuedFunctionEntityMapping) + { + fullTableName = $"{fullTableName}({tableValuedFunctionEntityMapping.ConstructFunctionParameterClause()})"; } return this.ResolveWithCultureInvariantFormatter($"{fullTableName}{sqlAlias}"); } + private string GetTableAliasNameInternal() + { + FormattableString tableAlias = $"{this.GetDelimitedIdentifier(this.EntityMapping.TableName)}"; + return this.ResolveWithCultureInvariantFormatter(tableAlias); + } + + private string GetFullFunctionCallClauseInternal(string tableAlias = null) + { + var sqlAlias = tableAlias == null + ? string.Empty + : $" AS {this.GetDelimitedIdentifier(tableAlias)}"; + + FormattableString fullTableName; + if (this.EntityMapping is ITableValuedFunctionEntityMapping tableValuedFunctionEntityMapping) + { + fullTableName = $"{this.EntityMapping.TableName}({tableValuedFunctionEntityMapping.ConstructFunctionParameterClause()}){sqlAlias}"; + } + else + { + fullTableName = $"{this.EntityMapping.TableName}{sqlAlias}"; + } + + return this.ResolveWithCultureInvariantFormatter(fullTableName); + } + /// /// Constructs a condition of form ColumnName=@PropertyName and ... with all the key columns (e.g. Id=@Id and EmployeeId=@EmployeeId) /// @@ -767,9 +821,9 @@ protected string ResolveWithSqlFormatter(FormattableString formattableString, bo [MethodImpl(MethodImplOptions.AggressiveInlining)] private void FindRelationship( GenericStatementSqlBuilder firstEntitySqlBuilder, - GenericStatementSqlBuilder secondEntitySqlBuilder, - out PropertyMapping[] firstEntityRelationshipPropertyMappings, - out PropertyMapping[] secondEntityRelationshipPropertyMappings, + GenericStatementSqlBuilder secondEntitySqlBuilder, + out PropertyMapping[] firstEntityRelationshipPropertyMappings, + out PropertyMapping[] secondEntityRelationshipPropertyMappings, ref SqlJoinType secondEntityJoinType) { var firstEntityMapping = firstEntitySqlBuilder.EntityMapping; diff --git a/Dapper.FastCrud/SqlStatements/RelationshipSqlStatements.cs b/Dapper.FastCrud/SqlStatements/RelationshipSqlStatements.cs index 863d47a..0953d39 100644 --- a/Dapper.FastCrud/SqlStatements/RelationshipSqlStatements.cs +++ b/Dapper.FastCrud/SqlStatements/RelationshipSqlStatements.cs @@ -76,7 +76,7 @@ public TEntity SelectById(IDbConnection connection, TEntity keyEntity, Aggregate out statement, out splitOnCondition, this.ConstructJoinInstructions(statementOptions, _joinedEntitiesSqlBuilders), - whereClause: $"{this.SqlBuilder.ConstructKeysWhereClause(this.SqlBuilder.GetTableName())}"); + whereClause: $"{this.SqlBuilder.ConstructKeysWhereClause(this.SqlBuilder.GetTableAliasName())}"); var relationshipInstanceBuilder = new RelationshipEntityInstanceBuilder(_allEntityMappings); var queriedEntityIdentities = this.Query(connection, @@ -101,7 +101,7 @@ public async Task SelectByIdAsync(IDbConnection connection, TEntity key out statement, out splitOnCondition, this.ConstructJoinInstructions(statementOptions, _joinedEntitiesSqlBuilders), - whereClause: $"{this.SqlBuilder.ConstructKeysWhereClause(this.SqlBuilder.GetTableName())}"); + whereClause: $"{this.SqlBuilder.ConstructKeysWhereClause(this.SqlBuilder.GetTableAliasName())}"); var relationshipInstanceBuilder = new RelationshipEntityInstanceBuilder(_allEntityMappings); var queriedEntityIdentities = await this.QueryAsync(connection, From 6d9dfb6407617981e30dc5dab3bec27cc6a4cb3a Mon Sep 17 00:00:00 2001 From: Fereydoon Karimi Date: Tue, 24 Dec 2019 11:16:45 +0330 Subject: [PATCH 2/4] SetDatabseName was addedd to EntityMapping configuration options. --- .../DialectOptions/MsSqlDatabaseOptions.cs | 3 +- .../PostreSqlDatabaseOptions.cs | 1 + .../Configuration/SqlDatabaseOptions.cs | 5 +++ Dapper.FastCrud/Mappings/EntityMapping.cs | 31 +++++++++++++++++++ Dapper.FastCrud/Sql.cs | 24 ++++++++++---- .../SqlBuilders/StatementSqlBuilder.cs | 25 ++++++++++++--- 6 files changed, 78 insertions(+), 11 deletions(-) diff --git a/Dapper.FastCrud/Configuration/DialectOptions/MsSqlDatabaseOptions.cs b/Dapper.FastCrud/Configuration/DialectOptions/MsSqlDatabaseOptions.cs index f20d188..319463a 100644 --- a/Dapper.FastCrud/Configuration/DialectOptions/MsSqlDatabaseOptions.cs +++ b/Dapper.FastCrud/Configuration/DialectOptions/MsSqlDatabaseOptions.cs @@ -1,12 +1,13 @@ namespace Dapper.FastCrud.Configuration.DialectOptions { - internal class MsSqlDatabaseOptions:SqlDatabaseOptions + internal class MsSqlDatabaseOptions : SqlDatabaseOptions { public MsSqlDatabaseOptions() { this.StartDelimiter = "["; this.EndDelimiter = "]"; this.IsUsingSchemas = true; + this.DefaultSchema = "dbo"; } } } diff --git a/Dapper.FastCrud/Configuration/DialectOptions/PostreSqlDatabaseOptions.cs b/Dapper.FastCrud/Configuration/DialectOptions/PostreSqlDatabaseOptions.cs index 7e7bd90..17445c7 100644 --- a/Dapper.FastCrud/Configuration/DialectOptions/PostreSqlDatabaseOptions.cs +++ b/Dapper.FastCrud/Configuration/DialectOptions/PostreSqlDatabaseOptions.cs @@ -6,6 +6,7 @@ public PostreSqlDatabaseOptions() { this.StartDelimiter = this.EndDelimiter = "\""; this.IsUsingSchemas = true; + this.DefaultSchema = "public"; } } } diff --git a/Dapper.FastCrud/Configuration/SqlDatabaseOptions.cs b/Dapper.FastCrud/Configuration/SqlDatabaseOptions.cs index d11969b..d6032ee 100644 --- a/Dapper.FastCrud/Configuration/SqlDatabaseOptions.cs +++ b/Dapper.FastCrud/Configuration/SqlDatabaseOptions.cs @@ -30,6 +30,11 @@ public SqlDatabaseOptions() /// public bool IsUsingSchemas { get; protected set; } + /// + /// Gets the default schema name. + /// + public string DefaultSchema { get; protected set; } + /// /// Gets the prefix used for named parameters /// diff --git a/Dapper.FastCrud/Mappings/EntityMapping.cs b/Dapper.FastCrud/Mappings/EntityMapping.cs index 771d899..a573f12 100644 --- a/Dapper.FastCrud/Mappings/EntityMapping.cs +++ b/Dapper.FastCrud/Mappings/EntityMapping.cs @@ -34,6 +34,10 @@ protected EntityMapping(Type entityType) _propertyMappings = new List(); _propertyNameMappingsMap = new Dictionary(); } + /// + /// The database associated with the entity. + /// + public string DatabaseName { get; protected set; } /// /// The table associated with the entity. @@ -188,6 +192,20 @@ internal void RemoveProperty(string propertyName) } } + /// + /// Sets the database name associated with your entity. + /// + /// Database name + protected void SetDatabaseNameInternal(string databaseName) + { + this.DatabaseName = databaseName; + + if (string.IsNullOrEmpty(this.SchemaName) && !string.IsNullOrEmpty(this.DatabaseName)) + { + this.SchemaName = OrmConfiguration.Conventions.GetDatabaseOptions(this.Dialect).DefaultSchema; + } + } + /// /// Sets the database table associated with your entity. /// @@ -359,6 +377,19 @@ public EntityMapping() /// protected abstract TEntityMapping CurrentEntityMapping { get; } + /// + /// Sets the database name associated with your entity. + /// + /// Database name + public TEntityMapping SetDatabaseName(string databaseName) + { + Requires.NotNullOrWhiteSpace(databaseName, nameof(databaseName)); + this.ValidateState(); + + this.SetDatabaseNameInternal(databaseName); + return this.CurrentEntityMapping; + } + /// /// Sets the database table associated with your entity. /// diff --git a/Dapper.FastCrud/Sql.cs b/Dapper.FastCrud/Sql.cs index 7a54b04..f446e0f 100644 --- a/Dapper.FastCrud/Sql.cs +++ b/Dapper.FastCrud/Sql.cs @@ -24,15 +24,27 @@ public static IFormattable Identifier(string sqlIdentifier) } /// - /// Returns a parameter formatter for an SQL function, allowing it to be properly formatted by adding delimiters. - /// Do not use this method for table or column names. + /// Returns a parameter formatter for the SQL function name of the main entity. + /// If you wish to resolve the table name of another entity, please use the generic overload instead. + /// The resolver can be used as-is in a formattable string expression. /// - /// An SQL identifier that is not a table or a column name. + /// Overrides the entity mapping used in the query method. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IFormattable Function(EntityMapping entityMappingOverride = null) + { + return new SqlParameterFormatter(SqlParameterElementType.Function, null, entityMappingOverride); + } + + /// + /// Returns a parameter formatter for the SQL function name of the provided entity. + /// If you wish to resolve the table name of the main entity, please use the non-generic overload instead. + /// The resolver can be used as-is in a formattable string expression. + /// + /// Overrides the entity mapping used in the query method. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IFormattable Function(string sqlFunction) + public static IFormattable Function(EntityMapping entityMappingOverride = null) { - Requires.NotNullOrEmpty(sqlFunction, nameof(sqlFunction)); - return new SqlParameterFormatter(SqlParameterElementType.Function, sqlFunction, null); + return new SqlEntityFormattableParameter(SqlParameterElementType.Function, null, entityMappingOverride); } /// diff --git a/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs b/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs index acc9677..444a3af 100644 --- a/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs +++ b/Dapper.FastCrud/SqlBuilders/StatementSqlBuilder.cs @@ -584,14 +584,31 @@ protected virtual string GetTableNameInternal(string tableAlias = null) : $" AS {this.GetDelimitedIdentifier(tableAlias)}"; FormattableString fullTableName; - string tableName = this.EntityMapping.TableName; - if ((!this.UsesSchemaForTableNames) || string.IsNullOrEmpty(this.EntityMapping.SchemaName)) + string tableName = this.GetDelimitedIdentifier(this.EntityMapping.TableName); + string schemaName = string.IsNullOrEmpty(this.EntityMapping.SchemaName) ? string.Empty : this.GetDelimitedIdentifier(this.EntityMapping.SchemaName); + string databaseName = string.IsNullOrEmpty(this.EntityMapping.DatabaseName) ? string.Empty : this.GetDelimitedIdentifier(this.EntityMapping.DatabaseName); + + if (!this.UsesSchemaForTableNames || string.IsNullOrEmpty(this.EntityMapping.SchemaName)) { - fullTableName = $"{this.GetDelimitedIdentifier(tableName)}"; + if (string.IsNullOrEmpty(databaseName)) + { + fullTableName = $"{tableName}"; + } + else + { + fullTableName = $"{databaseName}.{tableName}"; + } } else { - fullTableName = $"{this.GetDelimitedIdentifier(EntityMapping.SchemaName)}.{this.GetDelimitedIdentifier(tableName)}"; + if (string.IsNullOrEmpty(databaseName)) + { + fullTableName = $"{schemaName}.{tableName}"; + } + else + { + fullTableName = $"{databaseName}.{schemaName}.{tableName}"; + } } if (this.EntityMapping is ITableValuedFunctionEntityMapping tableValuedFunctionEntityMapping) From cad7af090af27b1138fdd4250438f3ac0d9ba700 Mon Sep 17 00:00:00 2001 From: Fereydoon Karimi Date: Tue, 21 Jan 2020 19:54:10 +0330 Subject: [PATCH 3/4] Support multi ChildParentRelationships with same foreignKey was added. --- Dapper.FastCrud/Mappings/EntityMapping.cs | 7 +-- Dapper.FastCrud/Mappings/PropertyMapping.cs | 50 +++++++++++++++------ 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/Dapper.FastCrud/Mappings/EntityMapping.cs b/Dapper.FastCrud/Mappings/EntityMapping.cs index a573f12..b9ad111 100644 --- a/Dapper.FastCrud/Mappings/EntityMapping.cs +++ b/Dapper.FastCrud/Mappings/EntityMapping.cs @@ -257,8 +257,9 @@ protected PropertyMapping SetPropertyInternal(PropertyMapping propertyMapping) private void ConstructChildParentEntityRelationships() { _childParentRelationships = _propertyMappings - .Where(propertyMapping => propertyMapping.ChildParentRelationship != null) - .GroupBy(propertyMapping => propertyMapping.ChildParentRelationship.ReferencedEntityType) + .Where(propertyMapping => propertyMapping.ChildParentRelationships != null) + .SelectMany(propertyMapping => propertyMapping.ChildParentRelationships.Select(item => new { ChildParentRelationship= item, PropertyMapping = propertyMapping })) + .GroupBy(relationship => relationship.ChildParentRelationship.ReferencedEntityType) .ToDictionary( groupedRelMappings => groupedRelMappings.Key, groupedRelMappings => @@ -302,7 +303,7 @@ private void ConstructChildParentEntityRelationships() .SingleOrDefault(propDescriptor => propDescriptor.Name == referencingEntityPropertyName); - return new EntityMappingRelationship(groupedRelMappings.Key, groupedRelMappings.OrderBy(propMapping => propMapping.ColumnOrder).ToArray(), referencingEntityPropertyDescriptor); + return new EntityMappingRelationship(groupedRelMappings.Key, groupedRelMappings.Select(propMapping=> propMapping.PropertyMapping).OrderBy(propMapping => propMapping.ColumnOrder).ToArray(), referencingEntityPropertyDescriptor); }); } diff --git a/Dapper.FastCrud/Mappings/PropertyMapping.cs b/Dapper.FastCrud/Mappings/PropertyMapping.cs index 05c1bd2..b9c1bea 100644 --- a/Dapper.FastCrud/Mappings/PropertyMapping.cs +++ b/Dapper.FastCrud/Mappings/PropertyMapping.cs @@ -1,9 +1,11 @@ namespace Dapper.FastCrud.Mappings { + using Dapper.FastCrud.Validations; using System; + using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations.Schema; - using Dapper.FastCrud.Validations; + using System.Linq; /// /// Reeturns mapping information held for a particular property. @@ -13,7 +15,7 @@ public class PropertyMapping private PropertyMappingOptions _options; private string _databaseColumnName; private int _columnOrder = -1; - private PropertyMappingRelationship _childParentRelationship; + private List _childParentRelationships; /// /// Default constructor. @@ -29,16 +31,16 @@ internal PropertyMapping(EntityMapping entityMapping, PropertyDescriptor descrip /// /// Gets or sets a child-parent relationship. /// - public PropertyMappingRelationship ChildParentRelationship + public List ChildParentRelationships { get { - return _childParentRelationship; + return _childParentRelationships; } set { this.ValidateState(); - _childParentRelationship = value; + _childParentRelationships = value; } } @@ -59,7 +61,29 @@ public PropertyMapping SetChildParentRelationship(string ref /// The name of the property on the current entity that would hold the referenced entity when instructed to do so in a JOIN statement. internal PropertyMapping SetChildParentRelationship(Type relatedEntityType, string referencingEntityPropertyName) { - this.ChildParentRelationship = new PropertyMappingRelationship(relatedEntityType, referencingEntityPropertyName); + this.ChildParentRelationships = new List { new PropertyMappingRelationship(relatedEntityType, referencingEntityPropertyName) }; + return this; + } + + /// + /// Add a foreign key relationship with another entity. + /// + /// Foreign entity type. + /// The name of the property on the current entity that would hold the referenced entity when instructed to do so in a JOIN statement. + public PropertyMapping AddChildParentRelationship(string referencingEntityPropertyName) + { + return this.AddChildParentRelationship(typeof(TRelatedEntityType), referencingEntityPropertyName); + } + + /// + /// Add a foreign key relationship with another entity. + /// + /// Foreign entity type. + /// The name of the property on the current entity that would hold the referenced entity when instructed to do so in a JOIN statement. + internal PropertyMapping AddChildParentRelationship(Type relatedEntityType, string referencingEntityPropertyName) + { + this.ChildParentRelationships = (this.ChildParentRelationships ?? new List()); + this.ChildParentRelationships.Add(new PropertyMappingRelationship(relatedEntityType, referencingEntityPropertyName)); return this; } @@ -68,7 +92,7 @@ internal PropertyMapping SetChildParentRelationship(Type relatedEntityType, stri /// public PropertyMapping RemoveChildParentRelationship() { - this.ChildParentRelationship = null; + this.ChildParentRelationships = null; return this; } @@ -404,13 +428,13 @@ public void Remove() internal PropertyMapping Clone(EntityMapping newEntityMapping) { var clonedPropertyMapping = new PropertyMapping(newEntityMapping, this.Descriptor) - { - _options = _options, - _childParentRelationship = _childParentRelationship == null ? null : new PropertyMappingRelationship(_childParentRelationship.ReferencedEntityType, _childParentRelationship.ReferencingPropertyName), - _databaseColumnName = this._databaseColumnName, - _columnOrder = _columnOrder + { + _options = _options, + _childParentRelationships = _childParentRelationships == null ? null : _childParentRelationships.Select(item => new PropertyMappingRelationship(item.ReferencedEntityType, item.ReferencingPropertyName)).ToList(), + _databaseColumnName = this._databaseColumnName, + _columnOrder = _columnOrder - }; + }; return clonedPropertyMapping; } From 7ab36aeaeda52035740cdd075108cffaeaaf686a Mon Sep 17 00:00:00 2001 From: Fereydoon Karimi Date: Sun, 3 May 2020 10:57:55 +0430 Subject: [PATCH 4/4] Upgrade .Net Standard. --- .../Dapper.FastCrud.Benchmarks.csproj | 7 +- Dapper.FastCrud.Benchmarks/app.config | 18 +-- .../Dapper.FastCrud.Tests.csproj | 3 +- .../Models/ModelGeneratorConfig1.cs | 123 ------------------ Dapper.FastCrud.Tests/app.config | 2 +- Dapper.FastCrud.sln | 19 +-- Dapper.FastCrud/Dapper.FastCrud.csproj | 111 +++++++--------- .../Properties/AssemblyInfo_unused.cs | 37 ------ 8 files changed, 66 insertions(+), 254 deletions(-) delete mode 100644 Dapper.FastCrud/Properties/AssemblyInfo_unused.cs diff --git a/Dapper.FastCrud.Benchmarks/Dapper.FastCrud.Benchmarks.csproj b/Dapper.FastCrud.Benchmarks/Dapper.FastCrud.Benchmarks.csproj index b6d426e..2929c1d 100644 --- a/Dapper.FastCrud.Benchmarks/Dapper.FastCrud.Benchmarks.csproj +++ b/Dapper.FastCrud.Benchmarks/Dapper.FastCrud.Benchmarks.csproj @@ -10,8 +10,9 @@ Properties Dapper.FastCrud.Benchmarks Dapper.FastCrud.Benchmarks - v4.5.2 + v4.7.2 512 + true @@ -87,10 +88,6 @@ - - {0fc75c39-9eb9-445c-ac0c-e1fbf79bbdf2} - Dapper.FastCrud.Tests - {a2b22949-0db7-4130-b813-420b839774b2} Dapper.FastCrud diff --git a/Dapper.FastCrud.Benchmarks/app.config b/Dapper.FastCrud.Benchmarks/app.config index 78b955e..1c6fc60 100644 --- a/Dapper.FastCrud.Benchmarks/app.config +++ b/Dapper.FastCrud.Benchmarks/app.config @@ -1,9 +1,9 @@ - + -
+
-
+
@@ -12,22 +12,22 @@ - + - + - + - + - + - \ No newline at end of file + diff --git a/Dapper.FastCrud.Tests/Dapper.FastCrud.Tests.csproj b/Dapper.FastCrud.Tests/Dapper.FastCrud.Tests.csproj index 69aa2db..2681e13 100644 --- a/Dapper.FastCrud.Tests/Dapper.FastCrud.Tests.csproj +++ b/Dapper.FastCrud.Tests/Dapper.FastCrud.Tests.csproj @@ -10,8 +10,9 @@ Properties Dapper.FastCrud.Tests Dapper.FastCrud.Tests - v4.5.2 + v4.6.1 512 + true diff --git a/Dapper.FastCrud.Tests/Models/ModelGeneratorConfig1.cs b/Dapper.FastCrud.Tests/Models/ModelGeneratorConfig1.cs index 35b55e0..8b13789 100644 --- a/Dapper.FastCrud.Tests/Models/ModelGeneratorConfig1.cs +++ b/Dapper.FastCrud.Tests/Models/ModelGeneratorConfig1.cs @@ -1,124 +1 @@ -// This file was automatically generated by the Dapper.FastCRUD T4 Template -// Do not make changes directly to this file - edit the template configuration instead -// -// The following connection settings were used to generate this file -// -// Connection String Name: `EntityGeneration` -// Provider: `System.Data.SqlClient` -// Connection String: `Data Source=(LocalDb)\MSSQLLocalDb;AttachDbFilename=D:\_Projects\Dapper.FastCRUD\Dapper.FastCRUD.Tests\App_Data\\EntityGenDatabase.mdf;Initial Catalog=EntityGenDatabase;Integrated Security=True` -// Include Views: `True` - -namespace Dapper.FastCrud.Tests.Models -{ - using System; - using System.ComponentModel.DataAnnotations; - using System.ComponentModel.DataAnnotations.Schema; - using System.Collections.Generic; - - /// - /// Represents the CrazyColumns table. - /// - [Table("CrazyColumns")] - public partial class CrazyColumn - { - /// - /// Id Column - /// - [Key] - public virtual int Id { get; set; } - /// - /// Test starting with a digit - /// - [Column("123mb")] - public virtual int _123mb { get; set; } - /// - /// Test starting with a C# keyword - /// - [Column("switch")] - public virtual int @switch { get; set; } - } - - /// - /// Represents the Employee table. - /// - [Table("Employee")] - public partial class Employee - { - /// - /// UserId Column - /// - [Key] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public virtual int UserId { get; set; } - /// - /// EmployeeId Column - /// - [Key] - [Dapper.FastCrud.DatabaseGeneratedDefaultValue] - public virtual Guid EmployeeId { get; set; } - /// - /// KeyPass Column - /// - [Dapper.FastCrud.DatabaseGeneratedDefaultValue] - public virtual Guid KeyPass { get; set; } - /// - /// LastName Column - /// - public virtual string LastName { get; set; } - /// - /// FirstName Column - /// - public virtual string FirstName { get; set; } - /// - /// BirthDate Column - /// - public virtual DateTime BirthDate { get; set; } - /// - /// WorkstationId Column - /// - [ForeignKey("Workstation")] - public virtual long? WorkstationId { get; set; } - /// - /// FullName Column - /// - [DatabaseGenerated(DatabaseGeneratedOption.Computed)] - public virtual string FullName { get; set; } - public virtual Workstation Workstation { get; set; } - } - - /// - /// Represents the Workstations table. - /// - [Table("Workstations")] - public partial class Workstation - { - /// - /// WorkstationId Column - /// - [Key] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public virtual long WorkstationId { get; set; } - /// - /// Name Column - /// - public virtual string Name { get; set; } - /// - /// AccessLevel Column - /// - [Dapper.FastCrud.DatabaseGeneratedDefaultValue] - public virtual int AccessLevel { get; set; } - /// - /// InventoryIndex Column - /// - public virtual int InventoryIndex { get; set; } - /// - /// 10PinSlots Column - /// - [Column("10PinSlots")] - public virtual int? _10PinSlots { get; set; } - public virtual IEnumerable Employees { get; set; } - } - -} - diff --git a/Dapper.FastCrud.Tests/app.config b/Dapper.FastCrud.Tests/app.config index 73e0c91..0adb6a1 100644 --- a/Dapper.FastCrud.Tests/app.config +++ b/Dapper.FastCrud.Tests/app.config @@ -23,7 +23,7 @@ - + diff --git a/Dapper.FastCrud.sln b/Dapper.FastCrud.sln index 97c27e0..47a54dc 100644 --- a/Dapper.FastCrud.sln +++ b/Dapper.FastCrud.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.16 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{54E575C2-7D28-48E1-91FD-694DEEB09CD0}" ProjectSection(SolutionItems) = preProject @@ -12,10 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.FastCrud", "Dapper.FastCrud\Dapper.FastCrud.csproj", "{A2B22949-0DB7-4130-B813-420B839774B2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.FastCrud.Tests", "Dapper.FastCrud.Tests\Dapper.FastCrud.Tests.csproj", "{0FC75C39-9EB9-445C-AC0C-E1FBF79BBDF2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.FastCrud.Benchmarks", "Dapper.FastCrud.Benchmarks\Dapper.FastCrud.Benchmarks.csproj", "{ED7BCE12-A776-437B-A1D1-9E3D3AE5A90B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.FastCrud.ModelGenerator", "Dapper.FastCrud.ModelGenerator\Dapper.FastCrud.ModelGenerator.csproj", "{61E1B675-C862-4AB8-828E-AE2360DDD11C}" EndProject Global @@ -28,14 +24,6 @@ Global {A2B22949-0DB7-4130-B813-420B839774B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {A2B22949-0DB7-4130-B813-420B839774B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {A2B22949-0DB7-4130-B813-420B839774B2}.Release|Any CPU.Build.0 = Release|Any CPU - {0FC75C39-9EB9-445C-AC0C-E1FBF79BBDF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0FC75C39-9EB9-445C-AC0C-E1FBF79BBDF2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0FC75C39-9EB9-445C-AC0C-E1FBF79BBDF2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0FC75C39-9EB9-445C-AC0C-E1FBF79BBDF2}.Release|Any CPU.Build.0 = Release|Any CPU - {ED7BCE12-A776-437B-A1D1-9E3D3AE5A90B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED7BCE12-A776-437B-A1D1-9E3D3AE5A90B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED7BCE12-A776-437B-A1D1-9E3D3AE5A90B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED7BCE12-A776-437B-A1D1-9E3D3AE5A90B}.Release|Any CPU.Build.0 = Release|Any CPU {61E1B675-C862-4AB8-828E-AE2360DDD11C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {61E1B675-C862-4AB8-828E-AE2360DDD11C}.Debug|Any CPU.Build.0 = Debug|Any CPU {61E1B675-C862-4AB8-828E-AE2360DDD11C}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -44,4 +32,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0E95A1DF-B9B5-4071-9F7E-DC1CE43EABD1} + EndGlobalSection EndGlobal diff --git a/Dapper.FastCrud/Dapper.FastCrud.csproj b/Dapper.FastCrud/Dapper.FastCrud.csproj index eb10a22..ca9f282 100644 --- a/Dapper.FastCrud/Dapper.FastCrud.csproj +++ b/Dapper.FastCrud/Dapper.FastCrud.csproj @@ -1,66 +1,49 @@  - - net45;net46;netstandard1.6 - Dapper.FastCrud - Dapper.FastCrud - true - true - bin\$(Configuration)\$(TargetFramework)\Dapper.FastCrud.xml - - embedded - True - - MoonStorm - Dapper.FastCrud - https://raw.githubusercontent.com/MoonStorm/Dapper.FastCRUD/master/logo.png - http://www.opensource.org/licenses/MIT - dapper crud orm sql sqlite mysql mssql localdb postgresql poco - true - The fastest micro-orm for Dapper - True - - Dapper.FastCrud is built around essential features of the C# 6 / VB that have finally raised the simplicity of raw SQL constructs to acceptable maintenance levels. These features leave no chance to mistypings or problems arising from db entity refactorings. Visual Studio 2015 or later is recommended. - - - - https://github.com/MoonStorm/Dapper.FastCRUD - - 1.0.0 - - - - - - - - - - - - - - - - - - - - - $(DefineConstants);NET_46_OR_GREATER - - - - $(DefineConstants);COREFX - - - - - - - - - - - - + + SAK + SAK + SAK + SAK + + + + netstandard2.0 + Dapper.FastCrud + Dapper.FastCrud + true + true + bin\$(Configuration)\$(TargetFramework)\Dapper.FastCrud.xml + embedded + True + 2.0.0 + MoonStorm + Dapper.FastCrud + https://raw.githubusercontent.com/MoonStorm/Dapper.FastCRUD/master/logo.png + http://www.opensource.org/licenses/MIT + dapper crud orm sql sqlite mysql mssql localdb postgresql poco + true + The fastest micro-orm for Dapper + True + + Dapper.FastCrud is built around essential features of the C# 6 / VB that have finally raised the simplicity of raw SQL constructs to acceptable maintenance levels. These features leave no chance to mistypings or problems arising from db entity refactorings. Visual Studio 2015 or later is recommended. + + + + https://github.com/MoonStorm/Dapper.FastCRUD + + 1.0.0 + + + + $(DefineConstants);COREFX + 2.0.0.0 + 2.0.0.0 + + + + + + + + \ No newline at end of file diff --git a/Dapper.FastCrud/Properties/AssemblyInfo_unused.cs b/Dapper.FastCrud/Properties/AssemblyInfo_unused.cs deleted file mode 100644 index 894fab9..0000000 --- a/Dapper.FastCrud/Properties/AssemblyInfo_unused.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Dapper.FastCrud")] -[assembly: AssemblyDescription("Dapper.FastCRUD is built around essential features of the C# 6 / VB 14 that have finally raised the simplicity of raw SQL constructs to acceptable maintenance levels. These features leave no chance to mistypings or problems arising from db entity refactorings. VS2015 or an equivalent build environment is recommended.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Dapper.FastCrud")] -[assembly: AssemblyCopyright("Copyright © Dan Cristiu 2017")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("0044043b-c8ec-497c-8b58-abe028014d24")] -[assembly:InternalsVisibleTo("Dapper.FastCrud.Tests")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")]