Skip to content

Commit

Permalink
Separate out into SQL project
Browse files Browse the repository at this point in the history
  • Loading branch information
CharlieJKendall committed Feb 1, 2020
1 parent cc61542 commit 4f3ec4d
Show file tree
Hide file tree
Showing 65 changed files with 1,540 additions and 1,010 deletions.
9 changes: 9 additions & 0 deletions src/Snoozle.SqlServer/Configuration/ISqlModelConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Snoozle.Abstractions;

namespace Snoozle.SqlServer.Configuration
{
public interface ISqlModelConfiguration : IModelConfiguration
{
string TableName { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/Snoozle.SqlServer/Configuration/ISqlPropertyConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Snoozle.Abstractions;
using System.Data;

namespace Snoozle.SqlServer.Configuration
{
public interface ISqlPropertyConfiguration : IPropertyConfiguration
{
SqlDbType? SqlDbType { get; set; }

string ColumnName { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Snoozle.Abstractions;

namespace Snoozle.SqlServer.Configuration
{
public interface ISqlResourceConfiguration : IResourceConfiguration<ISqlPropertyConfiguration, ISqlModelConfiguration>
{
}
}
21 changes: 21 additions & 0 deletions src/Snoozle.SqlServer/Configuration/ISqlRuntimeConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Snoozle.Abstractions;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace Snoozle.SqlServer.Configuration
{
public interface ISqlRuntimeConfiguration<out TResource> : IRuntimeConfiguration
where TResource : class, IRestResource
{
Func<SqlDataReader, TResource> GetSqlMapToResource { get; }
Func<object, SqlParameter> GetPrimaryKeySqlParameter { get; }
Func<object, List<SqlParameter>> GetNonPrimaryKeySqlParameters { get; }

string SelectAll { get; }
string SelectById { get; }
string DeleteById { get; }
string Insert { get; }
string UpdateById { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Snoozle.Abstractions;

namespace Snoozle.SqlServer.Configuration
{
public interface ISqlRuntimeConfigurationProvider : IRuntimeConfigurationProvider<ISqlRuntimeConfiguration<IRestResource>>
{
}
}
10 changes: 10 additions & 0 deletions src/Snoozle.SqlServer/Configuration/SqlModelConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Snoozle.Abstractions;

namespace Snoozle.SqlServer.Configuration
{
public class SqlModelConfiguration<TResource> : BaseModelConfiguration<TResource>, ISqlModelConfiguration
where TResource : class, IRestResource
{
public string TableName { get; set; } = typeof(TResource).Name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Snoozle.Abstractions;

namespace Snoozle.SqlServer.Configuration
{
public class SqlModelConfigurationBuilder : BaseModelConfigurationBuilder<ISqlModelConfiguration>, IModelConfigurationBuilder<ISqlModelConfiguration>
{
public SqlModelConfigurationBuilder(ISqlModelConfiguration modelConfiguration)
: base(modelConfiguration)
{
}
}
}
12 changes: 12 additions & 0 deletions src/Snoozle.SqlServer/Configuration/SqlPropertyConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Snoozle.Abstractions;
using System.Data;

namespace Snoozle.SqlServer.Configuration
{
public class SqlPropertyConfiguration : BasePropertyConfiguration, ISqlPropertyConfiguration
{
public SqlDbType? SqlDbType { get; set; }

public string ColumnName { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Snoozle.Abstractions;

namespace Snoozle.SqlServer.Configuration
{
public class SqlPropertyConfigurationBuilder<TResource, TProperty> : BasePropertyConfigurationBuilder<TResource, TProperty, ISqlPropertyConfiguration>, IPropertyConfigurationBuilder<TProperty, ISqlPropertyConfiguration>
where TResource : class, IRestResource
{
public SqlPropertyConfigurationBuilder(ISqlPropertyConfiguration propertyConfiguration)
: base(propertyConfiguration)
{
}
}
}
16 changes: 16 additions & 0 deletions src/Snoozle.SqlServer/Configuration/SqlResourceConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Snoozle.Abstractions;
using System.Collections.Generic;

namespace Snoozle.SqlServer.Configuration
{
public class SqlResourceConfiguration<TResource> : BaseResourceConfiguration<TResource, ISqlPropertyConfiguration, ISqlModelConfiguration>, ISqlResourceConfiguration
where TResource : class, IRestResource
{
public SqlResourceConfiguration(
ISqlModelConfiguration modelConfiguration,
IEnumerable<ISqlPropertyConfiguration> propertyConfigurations)
: base(modelConfiguration, propertyConfigurations)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using Snoozle.Abstractions;
using Snoozle.SqlServer.Extensions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;

namespace Snoozle.SqlServer.Configuration
{
public abstract class SqlResourceConfigurationBuilder<TResource> : BaseResourceConfigurationBuilder<TResource, ISqlPropertyConfiguration, ISqlResourceConfiguration, ISqlModelConfiguration>
where TResource : class, IRestResource
{
protected override IPropertyConfigurationBuilder<TProperty, ISqlPropertyConfiguration> CreatePropertyConfigurationBuilder<TProperty>(
ISqlPropertyConfiguration propertyConfiguration)
{
return new SqlPropertyConfigurationBuilder<TResource, TProperty>(propertyConfiguration);
}

protected override ISqlResourceConfiguration CreateResourceConfiguration()
{
return new SqlResourceConfiguration<TResource>(ModelConfiguration, PropertyConfigurations);
}

protected override ISqlModelConfiguration CreateModelConfiguration()
{
return new SqlModelConfiguration<TResource>();
}

protected override ISqlPropertyConfiguration CreatePropertyConfiguration()
{
return new SqlPropertyConfiguration();
}

protected override IModelConfigurationBuilder<ISqlModelConfiguration> CreateModelConfigurationBuilder()
{
return new SqlModelConfigurationBuilder(ModelConfiguration);
}

protected override void SetPropertyConfigurationDefaults()
{
base.SetPropertyConfigurationDefaults();

foreach (ISqlPropertyConfiguration propertyConfig in PropertyConfigurations)
{
propertyConfig.SqlDbType = GetDefaultSqlDbType(propertyConfig.PropertyType);
propertyConfig.ColumnName = propertyConfig.PropertyName;
}
}

private SqlDbType? GetDefaultSqlDbType(Type type)
{
type.TryUnwrapNullableType(out Type unwrappedType);
return Maps.DefaultSqlDbTypeMap.GetValueOrDefault(unwrappedType);
}
}

public static class Maps
{
public static ReadOnlyDictionary<Type, SqlDbType?> DefaultSqlDbTypeMap = new ReadOnlyDictionary<Type, SqlDbType?>(new Dictionary<Type, SqlDbType?>
{
{ typeof(long), SqlDbType.BigInt },
{ typeof(byte[]), SqlDbType.VarBinary },
{ typeof(bool), SqlDbType.Bit },
{ typeof(string), SqlDbType.NVarChar },
{ typeof(DateTime), SqlDbType.DateTime },
{ typeof(DateTimeOffset), SqlDbType.DateTimeOffset },
{ typeof(decimal), SqlDbType.Decimal },
{ typeof(double), SqlDbType.Float },
{ typeof(float), SqlDbType.Float },
{ typeof(int), SqlDbType.Int },
{ typeof(short), SqlDbType.SmallInt },
{ typeof(TimeSpan), SqlDbType.Time },
{ typeof(Guid), SqlDbType.UniqueIdentifier },
{ typeof(byte), SqlDbType.TinyInt }
});
}
}
43 changes: 43 additions & 0 deletions src/Snoozle.SqlServer/Configuration/SqlRuntimeConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Snoozle.Abstractions;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace Snoozle.SqlServer.Configuration
{
public class SqlRuntimeConfiguration<TResource> : BaseRuntimeConfiguration<ISqlPropertyConfiguration, ISqlModelConfiguration>, ISqlRuntimeConfiguration<TResource>
where TResource : class, IRestResource
{
// This is created by reflection, so be careful when changing/adding parameters
public SqlRuntimeConfiguration(
ISqlResourceConfiguration resourceConfiguration,
Func<SqlDataReader, TResource> getSqlMapToResource,
Func<object, SqlParameter> getPrimaryKeySqlParameter,
Func<object, List<SqlParameter>> getNonPrimaryKeySqlParameters,
string selectAll,
string selectById,
string deleteById,
string insert,
string updateById)
: base(resourceConfiguration)
{
GetSqlMapToResource = getSqlMapToResource;
GetPrimaryKeySqlParameter = getPrimaryKeySqlParameter;
GetNonPrimaryKeySqlParameters = getNonPrimaryKeySqlParameters;
SelectAll = selectAll;
SelectById = selectById;
DeleteById = deleteById;
Insert = insert;
UpdateById = updateById;
}

public Func<SqlDataReader, TResource> GetSqlMapToResource { get; }
public Func<object, SqlParameter> GetPrimaryKeySqlParameter { get; }
public Func<object, List<SqlParameter>> GetNonPrimaryKeySqlParameters { get; }
public string SelectAll { get; }
public string SelectById { get; }
public string DeleteById { get; }
public string Insert { get; }
public string UpdateById { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Snoozle.Abstractions;
using System;
using System.Collections.Generic;

namespace Snoozle.SqlServer.Configuration
{
public class SqlRuntimeConfigurationProvider : BaseRuntimeConfigurationProvider<ISqlRuntimeConfiguration<IRestResource>>, ISqlRuntimeConfigurationProvider
{
public SqlRuntimeConfigurationProvider(Dictionary<Type, ISqlRuntimeConfiguration<IRestResource>> runtimeConfigurations)
: base(runtimeConfigurations)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Snoozle.Abstractions;
using Snoozle.Extensions;
using Snoozle.SqlServer.Configuration;
using System.Data;
using System.Text.RegularExpressions;

namespace Snoozle.SqlServer.Extensions
{
public static class ModelConfigurationBuilderExtensions
{
private static Regex _tableNameRegex = new Regex(@"^[\p{L}_][\p{L}\p{N}@$#_]{0,127}$");

public static IModelConfigurationBuilder<ISqlModelConfiguration> HasTableName(
this IModelConfigurationBuilder<ISqlModelConfiguration> @this,
string tableName)
{
ExceptionHelper.ArgumentNull.ThrowIfNecessary(tableName, nameof(tableName));
ExceptionHelper.Argument.ThrowIfTrue(!_tableNameRegex.IsMatch(tableName), $"'{tableName}' is an invalid table name.", nameof(tableName));

@this.ModelConfiguration.TableName = tableName;

return @this;
}
}

public static class PropertyConfigurationBuilderExtensions
{
private static Regex _columnNameRegex = new Regex(@"^[a-zA-Z_][a-zA-Z0-9_ ]*$");

public static IPropertyConfigurationBuilder<TProperty, ISqlPropertyConfiguration> HasSqlDbType<TProperty>(
this IPropertyConfigurationBuilder<TProperty, ISqlPropertyConfiguration> @this,
SqlDbType sqlDbType)
{
@this.PropertyConfiguration.SqlDbType = sqlDbType;

return @this;
}

public static IPropertyConfigurationBuilder<TProperty, ISqlPropertyConfiguration> HasColumnName<TProperty>(
this IPropertyConfigurationBuilder<TProperty, ISqlPropertyConfiguration> @this,
string columnName)
{
ExceptionHelper.ArgumentNull.ThrowIfNecessary(columnName, nameof(columnName));
ExceptionHelper.Argument.ThrowIfTrue(!_columnNameRegex.IsMatch(columnName), $"'{columnName}' is an invalid column name.", nameof(columnName));

@this.PropertyConfiguration.ColumnName = columnName;

return @this;
}
}
}
74 changes: 74 additions & 0 deletions src/Snoozle.SqlServer/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Microsoft.Extensions.DependencyInjection;
using Snoozle.Abstractions;
using Snoozle.Core;
using Snoozle.Extensions;
using Snoozle.SqlServer.Configuration;
using Snoozle.SqlServer.Interfaces;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace Snoozle.SqlServer.Extensions
{
public static class ServiceCollectionExtensions
{
public static IMvcBuilder AddSnoozleSqlServer(this IMvcBuilder @this)
{
IServiceCollection serviceCollection = @this.Services;
ISqlRuntimeConfigurationProvider runtimeConfigurationProvider = BuildRuntimeConfigurationProvider();

serviceCollection.AddScoped<ISqlExecutor, SqlExecutor>();
serviceCollection.AddScoped<IDataProvider, SqlDataProvider>();
serviceCollection.AddSingleton(runtimeConfigurationProvider);

@this.AddSnoozleCore(runtimeConfigurationProvider);

return @this;
}

public static ISqlRuntimeConfigurationProvider BuildRuntimeConfigurationProvider()
{
IEnumerable<ISqlResourceConfiguration> resourceConfigurations =
Helpers.BuildResourceConfigurations<ISqlPropertyConfiguration, ISqlResourceConfiguration, ISqlModelConfiguration>(typeof(SqlResourceConfigurationBuilder<>));

// No need to register these with the DI container, as they are only used during startup
ISqlParamaterProvider sqlParamaterProvider = new SqlParameterProvider();
ISqlGenerator generator = new SqlGenerator(sqlParamaterProvider);
ISqlExpressionBuilder expressionBuilder = new SqlExpressionBuilder(sqlParamaterProvider);
Dictionary<Type, ISqlRuntimeConfiguration<IRestResource>> runtimeConfigurations = new Dictionary<Type, ISqlRuntimeConfiguration<IRestResource>>();

foreach (ISqlResourceConfiguration configuration in resourceConfigurations)
{
string selectAll = generator.SelectAll(configuration);
string selectById = generator.SelectById(configuration);
string deleteById = generator.DeleteById(configuration);
string updateById = generator.Update(configuration);
string insert = generator.Insert(configuration);

var createObjectRelationalMapFunc = typeof(ISqlExpressionBuilder)
.GetMethod(nameof(ISqlExpressionBuilder.CreateObjectRelationalMap))
.MakeGenericMethod(configuration.ResourceType)
.Invoke(expressionBuilder, new[] { configuration }) as Func<SqlDataReader, IRestResource>;

var getPrimaryKeySqlParameterFunc = expressionBuilder.GetPrimaryKeySqlParameter(configuration.PrimaryIdentifier);
var getNonPrimaryKeySqlParametersFunc = expressionBuilder.GetNonPrimaryKeySqlParameters(configuration);

var runtimeConfiguration = Activator.CreateInstance(
typeof(SqlRuntimeConfiguration<>).MakeGenericType(configuration.ResourceType),
configuration,
createObjectRelationalMapFunc,
getPrimaryKeySqlParameterFunc,
getNonPrimaryKeySqlParametersFunc,
selectAll,
selectById,
deleteById,
insert,
updateById) as ISqlRuntimeConfiguration<IRestResource>;

runtimeConfigurations.Add(configuration.ResourceType, runtimeConfiguration);
}

return new SqlRuntimeConfigurationProvider(runtimeConfigurations);
}
}
}
Loading

0 comments on commit 4f3ec4d

Please sign in to comment.