├── NuGet ├── _._ ├── Dashing.Weaver.targets ├── dashing-cli.nuspec ├── Init.ps1 └── dashing-weaver.nuspec ├── _config.yml ├── docs ├── _config.yml ├── dapper.md ├── assets │ └── css │ │ └── style.scss ├── configuration.md ├── seeding.md ├── migrations.md ├── queries.md ├── testing.md ├── configuration-indexes.md ├── async-support.md ├── configuration-conventions.md └── configuration-basics.md ├── dashing-icon.png ├── Dashing ├── AssemblyInfo.cs ├── Events │ ├── IEventListener.cs │ ├── IOnPreSaveEventListener.cs │ ├── IOnPostSaveEventListener.cs │ ├── IOnPreDeleteEventListener.cs │ ├── IOnPreInsertEventListener.cs │ ├── IOnPostDeleteEventListener.cs │ └── IOnPostInsertEventListener.cs ├── Configuration │ ├── ISeeder.cs │ ├── IMapT.cs │ ├── IConfiguration.cs │ ├── IndexColumnComparer.cs │ ├── RelationshipType.cs │ └── IMapper.cs ├── Migration │ ├── Statistics.cs │ ├── IStatisticsProvider.cs │ ├── StringBuilderExtensions.cs │ ├── TableNameEqualityComparer.cs │ ├── IMigrator.cs │ └── ColumnKeyValuePairEqualityComparer.cs ├── Engine │ ├── DML │ │ ├── IAliasProvider.cs │ │ ├── IAliasProviderFactory.cs │ │ ├── IInsertWriter.cs │ │ ├── IDeleteWriter.cs │ │ ├── IUpdateWriter.cs │ │ ├── Elements │ │ │ ├── ISqlElement.cs │ │ │ ├── StringElement.cs │ │ │ ├── ConstantElement.cs │ │ │ └── ColumnElement.cs │ │ ├── IBulkDeleteWriter.cs │ │ ├── ICountWriter.cs │ │ ├── IBulkUpdateWriter.cs │ │ ├── AutoNamingDynamicParameters.cs │ │ ├── IWhereClauseWriter.cs │ │ ├── SqlWriterResult.cs │ │ ├── ConstantChecker.cs │ │ ├── SelectWriterResult.cs │ │ ├── ISelectWriter.cs │ │ ├── IOrderClauseWriter.cs │ │ ├── WriterQueryCacheKey.cs │ │ ├── MemberExpressionFetchNodeVisitor.cs │ │ └── DeleteWriter.cs │ ├── DDL │ │ ├── IDropTableWriter.cs │ │ ├── ICreateTableWriter.cs │ │ ├── IAlterTableWriter.cs │ │ └── DropTableWriter.cs │ ├── DapperMapperGeneration │ │ ├── INonCollectionMapperGenerator.cs │ │ ├── IMultiCollectionMapperGenerator.cs │ │ └── ISingleCollectionMapperGenerator.cs │ ├── InMemory │ │ ├── InMemoryDbTransaction.cs │ │ ├── InMemoryKeyGenerator.cs │ │ ├── InMemoryDbConnection.cs │ │ └── WhereClauseOpEqualityRewriter.cs │ └── Dialects │ │ └── SqlServer2012Dialect.cs ├── ModelGeneration │ ├── IConvention.cs │ ├── IModelGenerator.cs │ └── DefaultConvention.cs ├── MultipleChoice.cs ├── SchemaReading │ ├── TemporalType.cs │ ├── ISchemaReader.cs │ ├── TableDto.cs │ ├── ForeignKeyDto.cs │ ├── IndexDto.cs │ ├── ColumnDto.cs │ └── SchemaReaderFactory.cs ├── IProjectedSelectQuery.cs ├── ReverseEngineering │ ├── IConvention.cs │ ├── IReverseEngineeringConfiguration.cs │ ├── IReverseEngineeringColumn.cs │ ├── IEngineer.cs │ ├── Column.cs │ └── DefaultConvention.cs ├── IDatabase.cs ├── Logging │ ├── LoggerDelegate.cs │ ├── LogLevel.cs │ ├── LogProviders │ │ ├── LibLogException.cs │ │ ├── DisposableAction.cs │ │ ├── TypeExtensions.cs │ │ └── TraceEventTypeValues.cs │ ├── ILog.cs │ └── ILogProvider.cs ├── CodeGeneration │ ├── ISetLogger.cs │ ├── IEnumerableAwaiter.cs │ ├── ITrackedEntity.cs │ ├── DelegateProjectionResult.cs │ ├── ITrackedEntityInspector.cs │ ├── FetchCollectionAwaiter.cs │ └── TrackingCollection.cs ├── Versioning │ └── IVersionedEntity.cs ├── IAnswerProvider.cs ├── ILogger.cs ├── IFetchMany.cs ├── Extensions │ ├── AssemblyExtensions.cs │ ├── DictionaryExtensions.cs │ ├── ReferenceEqualityComparer.cs │ ├── DapperExtensions.cs │ ├── EnumerableExtensions.cs │ └── AsyncLock.cs ├── IExecuteSelectQueries.cs ├── IProjectedSelectQueryExecutor.cs ├── IEnumerableSelectQuery.cs ├── Page.cs ├── ISession.cs ├── OrderClause.cs ├── SessionExtensions.cs ├── InMemoryDatabase.cs ├── FetchMany.cs └── Dashing.csproj ├── references ├── Dapper │ ├── Dapper.dll │ └── Dapper.pdb └── LightSpeed │ ├── Mindscape.LightSpeed.dll │ └── Mindscape.LightSpeed.Linq.dll ├── Dashing.Tests ├── TestDomain │ ├── NoPrimary.cs │ ├── IEnableable.cs │ ├── Customer.cs │ ├── Delivery.cs │ ├── LineItem.cs │ ├── Tag.cs │ ├── Circular │ │ ├── A.cs │ │ ├── B.cs │ │ └── C.cs │ ├── BoolClass.cs │ ├── ThingThatReferencesOrderNullable.cs │ ├── Guid │ │ └── EntityWithGuidPk.cs │ ├── Order.cs │ ├── Like.cs │ ├── PostTag.cs │ ├── Pair.cs │ ├── OneToOneLeft.cs │ ├── OneToOneRight.cs │ ├── OneToOne │ │ ├── OneToOneLeft.cs │ │ ├── OneToOneRight.cs │ │ └── Category.cs │ ├── SimpleClass.cs │ ├── Constructor │ │ └── ClassWithConstructor.cs │ ├── Category.cs │ ├── ThingWithNullable.cs │ ├── User.cs │ ├── Versioning │ │ └── VersionedEntity.cs │ ├── Blog.cs │ ├── Comment.cs │ └── Post.cs ├── MockConfiguration.cs ├── Engine │ ├── InMemory │ │ ├── TestDomain │ │ │ ├── IEnableable.cs │ │ │ ├── Tag.cs │ │ │ ├── BoolClass.cs │ │ │ ├── ThingWithLongPrimaryKey.cs │ │ │ ├── ThingWithStringPrimaryKey.cs │ │ │ ├── Pair.cs │ │ │ ├── Like.cs │ │ │ ├── PostTag.cs │ │ │ ├── OneToOne │ │ │ │ ├── OneToOneLeft.cs │ │ │ │ ├── OneToOneRight.cs │ │ │ │ └── Category.cs │ │ │ ├── User.cs │ │ │ ├── Blog.cs │ │ │ ├── Comment.cs │ │ │ └── Post.cs │ │ ├── WhereClauseCaseInsensitiveRewriterTests.cs │ │ ├── TestConfiguration.cs │ │ └── ExpressionExtensions.cs │ └── DML │ │ ├── FetchTreeParserTests.cs │ │ └── WhereClauseWriterPerformanceTests.cs ├── StringExtensions.cs ├── Configuration │ ├── SelfReferenceTests │ │ ├── Domain │ │ │ ├── Tag.cs │ │ │ ├── Like.cs │ │ │ ├── PostTag.cs │ │ │ ├── Pair.cs │ │ │ ├── OneToOneLeft.cs │ │ │ ├── OneToOneRight.cs │ │ │ ├── Category.cs │ │ │ ├── User.cs │ │ │ ├── Blog.cs │ │ │ ├── Comment.cs │ │ │ └── Post.cs │ │ └── TestConfig.cs │ ├── AddNamespaceTests.cs │ ├── AddNamespaceDomain │ │ └── AddNamespaceConfiguration.cs │ ├── ReverseEngineer │ │ └── Sandbox.cs │ └── ColumnTests.cs ├── TestConfig.cs ├── Migration │ └── TableNameEqualityComparerTests.cs ├── MutableConfiguration.cs ├── CustomConfig.cs ├── App.config ├── Extensions │ └── DynamicParametersExtensions.cs ├── NeedToDash.cs └── Dashing.Tests.csproj ├── Dashing.Weaving.Sample ├── Domain │ ├── Tracking │ │ ├── IntPk.cs │ │ ├── LongPk.cs │ │ ├── StringPk.cs │ │ ├── GuidPK.cs │ │ └── References.cs │ ├── FooType.cs │ ├── Dog.cs │ ├── Animal.cs │ ├── Duck.cs │ ├── EntityWithStringPrimaryKey.cs │ ├── EntityWithGuidPrimaryKey.cs │ ├── EntityReferencingEntityWithPrimaryKey.cs │ ├── ReferencesAnotherAssembly.cs │ ├── IveGotMethods.cs │ ├── Foo.cs │ ├── Bar.cs │ ├── Starship.cs │ └── Whopper.cs ├── Program.cs ├── App.config ├── Dashing.Weaving.Sample.csproj └── Config.cs ├── Dashing.Weaving.Tests ├── WeavingFixture.cs ├── WeavingTests.cs └── ForeignKeyTests.cs ├── Dashing.Cli ├── app.config ├── NullStatisticsProvider.cs ├── Properties │ └── launchSettings.json ├── DbProviderFactoryFactory.cs ├── Seeder.cs └── Program.cs ├── Dashing.Weaving.Sample2 ├── Dashing.Weaving.Sample2.csproj └── AnotherAssembliesClass.cs ├── Nuget.config ├── Dashing.IntegrationTests ├── TestDomain │ ├── Tag.cs │ ├── More │ │ ├── Room.cs │ │ ├── RoomSlot.cs │ │ ├── Bed.cs │ │ ├── Question.cs │ │ ├── Booking.cs │ │ ├── QuestionResponse.cs │ │ ├── Questionnaire.cs │ │ └── QuestionnaireResponse.cs │ ├── PostTag.cs │ ├── Versioned │ │ ├── VersionedConfiguration.cs │ │ ├── NonVersioned │ │ │ ├── NonVersionedConfiguration.cs │ │ │ └── VersionedEntity.cs │ │ └── VersionedEntity.cs │ ├── User.cs │ ├── Comment.cs │ ├── Blog.cs │ └── Post.cs ├── App.config ├── Setup │ ├── SessionDataGenerator.cs │ ├── Configuration.cs │ ├── TestSessionWrapper.cs │ ├── MySqlServerDatabase.cs │ ├── SqlLiteConfiguration.cs │ ├── SqlServerDatabase.cs │ ├── SqlSessionCreatorExtensions.cs │ └── TestDatabaseGenerator.cs ├── Tests │ ├── OuterJoinDisjunctionTransformerTests.cs │ ├── SelectTests.cs │ ├── DapperWrapperTests.cs │ ├── TransactionTests.cs │ ├── EnumeratingTests.cs │ └── AsyncTests.cs └── packages.config ├── Dashing.Weaver ├── Weaving │ ├── Weavers │ │ ├── ITaskLogHelper.cs │ │ └── IWeaver.cs │ ├── MapDefinition.cs │ ├── NullLogger.cs │ ├── ColumnDefinition.cs │ ├── TypeDefinitionExtensions.cs │ └── ModuleDefinitionExtensions.cs ├── WeaveException.cs ├── Program.cs ├── Test.ini └── Properties │ └── launchSettings.json ├── Dashing.PerformanceTests ├── Domain │ ├── Tag.cs │ ├── PostTag.cs │ ├── User.cs │ ├── Comment.cs │ ├── Blog.cs │ └── Post.cs ├── Tests │ ├── Dashing │ │ └── DashingConfiguration.cs │ └── EntityFramework │ │ └── EfContext.cs ├── Providers.cs ├── Test.cs ├── Dashing.PerformanceTests.csproj └── App.config ├── Package Dashing.bat ├── Dashing.CommandLine ├── ColorContext.cs ├── LogConfiguration.cs └── AssemblyContext.cs └── LICENSE /NuGet/_._: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: "mmistakes/minimal-mistakes" 2 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate 2 | google_analytics: UA-125024109-1 3 | -------------------------------------------------------------------------------- /dashing-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractLeap/dashing/HEAD/dashing-icon.png -------------------------------------------------------------------------------- /Dashing/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Dashing.Tests")] -------------------------------------------------------------------------------- /references/Dapper/Dapper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractLeap/dashing/HEAD/references/Dapper/Dapper.dll -------------------------------------------------------------------------------- /references/Dapper/Dapper.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractLeap/dashing/HEAD/references/Dapper/Dapper.pdb -------------------------------------------------------------------------------- /Dashing/Events/IEventListener.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Events { 2 | public interface IEventListener { 3 | } 4 | } -------------------------------------------------------------------------------- /references/LightSpeed/Mindscape.LightSpeed.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractLeap/dashing/HEAD/references/LightSpeed/Mindscape.LightSpeed.dll -------------------------------------------------------------------------------- /Dashing/Configuration/ISeeder.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Configuration { 2 | public interface ISeeder { 3 | void Seed(ISession session); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/Migration/Statistics.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Migration { 2 | public class Statistics { 3 | public bool HasRows { get; set; } 4 | } 5 | } -------------------------------------------------------------------------------- /references/LightSpeed/Mindscape.LightSpeed.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractLeap/dashing/HEAD/references/LightSpeed/Mindscape.LightSpeed.Linq.dll -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/NoPrimary.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class NoPrimary { 3 | public string Name { get; set; } 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/IEnableable.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public interface IEnableable { 3 | bool IsEnabled { get; set; } 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Tests/MockConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests { 2 | using Dashing.Configuration; 3 | 4 | public class MockConfiguration : BaseConfiguration { 5 | } 6 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IAliasProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | public interface IAliasProvider { 3 | string GetAlias(BaseQueryNode queryNode); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Tracking/IntPk.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain.Tracking { 2 | public class IntPk { 3 | public int Id { get; set; } 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Tracking/LongPk.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain.Tracking { 2 | public class LongPk { 3 | public long Id { get; set; } 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample { 2 | internal class Program { 3 | private static void Main(string[] args) { 4 | } 5 | } 6 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IAliasProviderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | public interface IAliasProviderFactory { 3 | IAliasProvider GetAliasProvider(); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/ModelGeneration/IConvention.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ModelGeneration { 2 | public interface IConvention { 3 | string ClassNameForTable(string tableName); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/FooType.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public enum FooType { 3 | One, 4 | 5 | Two, 6 | 7 | Three 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Tracking/StringPk.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain.Tracking { 2 | public class StringPk { 3 | public string Id { get; set; } 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Tests/WeavingFixture.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Tests { 2 | using Xunit; 3 | 4 | [Collection("Weaving Tests")] 5 | public class WeavingFixture { 6 | } 7 | } -------------------------------------------------------------------------------- /NuGet/Dashing.Weaver.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Dashing.Cli/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/IEnableable.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public interface IEnableable { 3 | bool IsEnabled { get; set; } 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/MultipleChoice.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | public class MultipleChoice { 3 | public string DisplayString { get; set; } 4 | 5 | public T Choice { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Tracking/GuidPK.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain.Tracking { 2 | using System; 3 | 4 | public class GuidPk { 5 | public Guid Id { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing/Events/IOnPreSaveEventListener.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Events { 2 | public interface IOnPreSaveEventListener : IEventListener { 3 | void OnPreSave(object entity, ISession session); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/SchemaReading/TemporalType.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.SchemaReading { 2 | public enum TemporalType { 3 | NonTemporal = 0, 4 | HistoryTable = 1, 5 | TemporalTable = 2 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Customer.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class Customer { 3 | public int CustomerId { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Delivery.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class Delivery { 3 | public int DeliveryId { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/LineItem.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class LineItem { 3 | public int LineItemId { get; set; } 4 | 5 | public Order Order { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample2/Dashing.Weaving.Sample2.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net46;net9.0 5 | 6 | 7 | -------------------------------------------------------------------------------- /Dashing/Events/IOnPostSaveEventListener.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Events { 2 | public interface IOnPostSaveEventListener : IEventListener { 3 | void OnPostSave(object entity, ISession session); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/Events/IOnPreDeleteEventListener.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Events { 2 | public interface IOnPreDeleteEventListener : IEventListener { 3 | void OnPreDelete(object entity, ISession session); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/Events/IOnPreInsertEventListener.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Events { 2 | public interface IOnPreInsertEventListener : IEventListener { 3 | void OnPreInsert(object entity, ISession session); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/IProjectedSelectQuery.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | public interface IProjectedSelectQuery : IEnumerableSelectQuery 3 | where TBase : class, new() { 4 | 5 | } 6 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Tag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class Tag { 3 | public virtual int TagId { get; set; } 4 | 5 | public virtual string Content { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Dog.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public class Dog : Animal { 3 | public int Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IInsertWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | public interface IInsertWriter { 3 | SqlWriterResult GenerateSql(T entity); 4 | 5 | string GenerateGetIdSql(); 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing/Events/IOnPostDeleteEventListener.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Events { 2 | public interface IOnPostDeleteEventListener : IEventListener { 3 | void OnPostDelete(object entity, ISession session); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing/Events/IOnPostInsertEventListener.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Events { 2 | public interface IOnPostInsertEventListener : IEventListener { 3 | void OnPostInsert(object entity, ISession session); 4 | } 5 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Animal.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public abstract class Animal { 3 | public int Legs { get; set; } 4 | 5 | public int Arms { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Tag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain { 2 | public class Tag { 3 | public long TagId { get; set; } 4 | 5 | public string Content { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Circular/A.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.Tests.TestDomain.Circular { 2 | public class A { 3 | public virtual int AId { get; set; } 4 | 5 | public virtual B B { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Circular/B.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.Tests.TestDomain.Circular { 2 | public class B { 3 | public virtual int BId { get; set; } 4 | 5 | public virtual C C { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Circular/C.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.Tests.TestDomain.Circular { 2 | public class C { 3 | public virtual int CId { get; set; } 4 | 5 | public virtual A A { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Weaving/Weavers/ITaskLogHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver.Weaving.Weavers { 2 | using ILogger = Dashing.ILogger; 3 | 4 | public interface ITaskLogHelper { 5 | ILogger Log { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Domain/Tag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Domain { 2 | public class Tag { 3 | public virtual int TagId { get; set; } 4 | 5 | public virtual string Content { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/BoolClass.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class BoolClass { 3 | public virtual int BoolClassId { get; set; } 4 | 5 | public virtual bool IsFoo { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample2/AnotherAssembliesClass.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample2 { 2 | public class AnotherAssembliesClass { 3 | public int Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IDeleteWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System.Collections.Generic; 3 | 4 | public interface IDeleteWriter { 5 | SqlWriterResult GenerateSql(IEnumerable entities); 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IUpdateWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System.Collections.Generic; 3 | 4 | public interface IUpdateWriter { 5 | SqlWriterResult GenerateSql(IEnumerable entities); 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing/SchemaReading/ISchemaReader.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.SchemaReading { 2 | using System.Data; 3 | 4 | public interface ISchemaReader { 5 | Database Read(IDbConnection dbConnection, string databaseName); 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/Room.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | public class Room { 3 | public long RoomId { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/RoomSlot.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | public class RoomSlot { 3 | public long RoomSlotId { get; set; } 4 | 5 | public Room Room { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/Tag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class Tag { 3 | public virtual int TagId { get; set; } 4 | 5 | public virtual string Content { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/ThingThatReferencesOrderNullable.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class ThingThatReferencesOrderNullable { 3 | public int Id { get; set; } 4 | 5 | public Order Order { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Duck.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public class Duck { 3 | public int Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | 7 | public Foo Foo { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/EntityWithStringPrimaryKey.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public class EntityWithStringPrimaryKey { 3 | public string Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing/Engine/DDL/IDropTableWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DDL { 2 | using Dashing.Configuration; 3 | 4 | public interface IDropTableWriter { 5 | string DropTable(IMap map); 6 | 7 | string DropTableIfExists(IMap map); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/BoolClass.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class BoolClass { 3 | public virtual int BoolClassId { get; set; } 4 | 5 | public virtual bool IsFoo { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.Tests { 2 | public static class StringExtensions { 3 | public static string NormalizeNewlines(this string value) { 4 | return value.Replace(@"\r\n", @"\n"); 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Guid/EntityWithGuidPk.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain.Guid { 2 | using System; 3 | 4 | public class EntityWithGuidPk { 5 | public Guid Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Weaver/WeaveException.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver { 2 | using System; 3 | 4 | internal class WeaveException : Exception 5 | { 6 | public WeaveException(string message) : base(message) 7 | { 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Dashing/ReverseEngineering/IConvention.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ReverseEngineering { 2 | public interface IConvention { 3 | string PropertyNameForManyToOneColumnName(string columnName); 4 | 5 | string ClassNameFor(string tableName); 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/ThingWithLongPrimaryKey.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class ThingWithLongPrimaryKey { 3 | public long Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Order.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class Order { 3 | public int OrderId { get; set; } 4 | 5 | public Delivery Delivery { get; set; } 6 | 7 | public Customer Customer { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/PostTag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain { 2 | public class PostTag { 3 | public long PostTagId { get; set; } 4 | 5 | public Post Post { get; set; } 6 | 7 | public Tag Tag { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/Tag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | public class Tag { 3 | public virtual int TagId { get; set; } 4 | 5 | public virtual string Content { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/ThingWithStringPrimaryKey.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class ThingWithStringPrimaryKey { 3 | public string Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Like.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class Like { 3 | public virtual int LikeId { get; set; } 4 | 5 | public virtual User User { get; set; } 6 | 7 | public virtual Comment Comment { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/EntityWithGuidPrimaryKey.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | using System; 3 | 4 | public class EntityWithGuidPrimaryKey { 5 | public Guid Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/PostTag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class PostTag { 3 | public virtual int PostTagId { get; set; } 4 | 5 | public virtual Post Post { get; set; } 6 | 7 | public virtual Tag ElTag { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Pair.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class Pair { 3 | public virtual int PairId { get; set; } 4 | 5 | public virtual Pair References { get; set; } 6 | 7 | public virtual Pair ReferencedBy { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/Bed.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | public class Bed { 3 | public long BedId { get; set; } 4 | 5 | public RoomSlot RoomSlot { get; set; } 6 | 7 | public Booking Booking { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Domain/PostTag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Domain { 2 | public class PostTag { 3 | public virtual int PostTagId { get; set; } 4 | 5 | public virtual Post Post { get; set; } 6 | 7 | public virtual Tag Tag { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/Pair.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class Pair { 3 | public int PairId { get; set; } 4 | 5 | public Blog Left { get; set; } 6 | 7 | public Blog Right { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/WhereClauseCaseInsensitiveRewriterTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory { 2 | using Xunit; 3 | 4 | public class WhereClauseCaseInsensitiveRewriterTests { 5 | [Fact] 6 | public void ContainsGetsRewritten() { 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests { 2 | using Dashing.Configuration; 3 | using Dashing.Tests.TestDomain; 4 | 5 | public class TestConfig : BaseConfiguration { 6 | public TestConfig() { 7 | this.AddNamespaceOf(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Dashing/Migration/IStatisticsProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Migration { 2 | using System.Collections.Generic; 3 | 4 | using Dashing.Configuration; 5 | 6 | public interface IStatisticsProvider { 7 | IDictionary GetStatistics(IEnumerable fromMaps); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/OneToOneLeft.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class OneToOneLeft { 3 | public virtual int OneToOneLeftId { get; set; } 4 | 5 | public virtual OneToOneRight Right { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/OneToOneRight.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class OneToOneRight { 3 | public virtual int OneToOneRightId { get; set; } 4 | 5 | public virtual OneToOneLeft Left { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/ReverseEngineering/IReverseEngineeringConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ReverseEngineering { 2 | using System; 3 | 4 | using Dashing.Configuration; 5 | 6 | internal interface IReverseEngineeringConfiguration : IConfiguration { 7 | void AddMap(Type type, IMap map); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/Question.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | public class Question { 3 | public long QuestionId { get; set; } 4 | 5 | public Questionnaire Questionnaire { get; set; } 6 | 7 | public string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/Like.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class Like { 3 | public virtual int LikeId { get; set; } 4 | 5 | public virtual User User { get; set; } 6 | 7 | public virtual Comment Comment { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/PostTag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class PostTag { 3 | public virtual int PostTagId { get; set; } 4 | 5 | public virtual Post Post { get; set; } 6 | 7 | public virtual Tag ElTag { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/IDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Data; 3 | 4 | public interface IDatabase { 5 | ISession BeginSession(IDbConnection connection = null, IDbTransaction transaction = null); 6 | 7 | ISession BeginTransactionLessSession(IDbConnection connection = null); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/Elements/ISqlElement.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML.Elements { 2 | using System.Text; 3 | 4 | using Dashing.Engine.Dialects; 5 | 6 | internal interface ISqlElement { 7 | void Append(StringBuilder stringBuilder, ISqlDialect dialect, IAliasProvider aliasProvider); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/OneToOne/OneToOneLeft.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain.OneToOne { 2 | public class OneToOneLeft { 3 | public virtual int OneToOneLeftId { get; set; } 4 | 5 | public virtual OneToOneRight Right { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/OneToOne/OneToOneRight.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain.OneToOne { 2 | public class OneToOneRight { 3 | public virtual int OneToOneRightId { get; set; } 4 | 5 | public virtual OneToOneLeft Left { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IBulkDeleteWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | public interface IBulkDeleteWriter { 7 | SqlWriterResult GenerateBulkSql(IEnumerable>> predicates); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/Like.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | public class Like { 3 | public virtual int LikeId { get; set; } 4 | 5 | public virtual User User { get; set; } 6 | 7 | public virtual Comment Comment { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/PostTag.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | public class PostTag { 3 | public virtual int PostTagId { get; set; } 4 | 5 | public virtual Post Post { get; set; } 6 | 7 | public virtual Tag Tag { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/Pair.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | public class Pair { 3 | public virtual int PairId { get; set; } 4 | 5 | public virtual Pair References { get; set; } 6 | 7 | public virtual Pair ReferencedBy { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Versioned/VersionedConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.Versioned { 2 | using Dashing.Configuration; 3 | public class VersionedConfiguration : BaseConfiguration { 4 | public VersionedConfiguration() { 5 | this.Add(); 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Dashing/Engine/DapperMapperGeneration/INonCollectionMapperGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DapperMapperGeneration { 2 | using System; 3 | 4 | using Dashing.Engine.DML; 5 | 6 | internal interface INonCollectionMapperGenerator { 7 | Tuple GenerateNonCollectionMapper(QueryTree mapQueryTree); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/SimpleClass.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.Tests.TestDomain { 2 | using System; 3 | 4 | public class SimpleClass { 5 | public virtual int SimpleClassId { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | 9 | public virtual DateTime CreatedDate { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Weaving/Weavers/IWeaver.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver.Weaving.Weavers { 2 | using System.Collections.Generic; 3 | 4 | using Mono.Cecil; 5 | 6 | public interface IWeaver { 7 | void Weave(AssemblyDefinition assemblyDefinition, TypeDefinition typeDefinition, IEnumerable columnDefinitions); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/Logging/LoggerDelegate.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Logging 2 | { 3 | using System; 4 | 5 | #if !LIBLOG_PROVIDERS_ONLY || LIBLOG_PUBLIC 6 | public 7 | #else 8 | internal 9 | #endif 10 | delegate bool Logger(LogLevel logLevel, Func messageFunc, Exception exception = null, params object[] formatParameters); 11 | } 12 | -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/Booking.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | using System.Collections.Generic; 3 | 4 | public class Booking { 5 | public long BookingId { get; set; } 6 | 7 | public bool IsFoo { get; set; } 8 | 9 | public IList Beds { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/QuestionResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | public class QuestionResponse { 3 | public long QuestionResponseId { get; set; } 4 | 5 | public QuestionnaireResponse QuestionnaireResponse { get; set; } 6 | 7 | public Question Question { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/OneToOne/OneToOneLeft.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain.OneToOne { 2 | public class OneToOneLeft { 3 | public virtual int OneToOneLeftId { get; set; } 4 | 5 | public virtual OneToOneRight Right { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/OneToOne/OneToOneRight.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain.OneToOne { 2 | public class OneToOneRight { 3 | public virtual int OneToOneRightId { get; set; } 4 | 5 | public virtual OneToOneLeft Left { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/CodeGeneration/ISetLogger.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CodeGeneration { 2 | using System.Collections.Generic; 3 | 4 | public interface ISetLogger { 5 | IEnumerable GetSetProperties(); 6 | 7 | bool IsSetLoggingEnabled(); 8 | 9 | void EnableSetLogging(); 10 | 11 | void DisableSetLogging(); 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/OneToOneLeft.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | public class OneToOneLeft { 3 | public virtual int OneToOneLeftId { get; set; } 4 | 5 | public virtual OneToOneRight Right { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/OneToOneRight.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | public class OneToOneRight { 3 | public virtual int OneToOneRightId { get; set; } 4 | 5 | public virtual OneToOneLeft Left { get; set; } 6 | 7 | public virtual string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/EntityReferencingEntityWithPrimaryKey.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public class EntityReferencingEntityWithPrimaryKey { 3 | public long Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | 7 | public EntityWithStringPrimaryKey EntityWithStringPrimaryKey { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/Versioning/IVersionedEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Versioning { 2 | using System; 3 | 4 | public interface IVersionedEntity { 5 | TUserId SessionUser { get; set; } 6 | 7 | TUserId CreatedBy { get; set; } 8 | 9 | DateTime SysStartTime { get; set; } 10 | 11 | DateTime SysEndTime { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Weaving/MapDefinition.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Dashing.Weaver.Weaving { 3 | using System.Collections.Generic; 4 | 5 | public class MapDefinition { 6 | public string AssemblyPath { get; set; } 7 | 8 | public string TypeFullName { get; set; } 9 | 10 | public IList ColumnDefinitions { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/ReferencesAnotherAssembly.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | using Dashing.Weaving.Sample2; 3 | 4 | public class ReferencesAnotherAssembly { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public AnotherAssembliesClass TotherClass { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/Questionnaire.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | using System.Collections.Generic; 3 | 4 | public class Questionnaire { 5 | public long QuestionnaireId { get; set; } 6 | 7 | public IList Questions { get; set; } 8 | 9 | public string Name { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Versioned/NonVersioned/NonVersionedConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.Versioned.NonVersioned { 2 | using Dashing.Configuration; 3 | 4 | public class NonVersionedConfiguration : BaseConfiguration { 5 | public NonVersionedConfiguration() { 6 | this.Add(); 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing/Configuration/IMapT.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Configuration { 2 | public interface IMap : IMap { 3 | object GetPrimaryKeyValue(T entity); 4 | 5 | void SetPrimaryKeyValue(T entity, object value); 6 | 7 | object GetColumnValue(T entity, IColumn column); 8 | 9 | void SetColumnValue(T entity, IColumn column, object value); 10 | } 11 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/ICountWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | public interface ICountWriter { 3 | SqlWriterResult GenerateCountSql(SelectQuery selectQuery) where T : class, new(); 4 | 5 | SqlWriterResult GenerateCountSql(ProjectedSelectQuery projectedSelectQuery) 6 | where TBase : class, new(); 7 | } 8 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/TestConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests { 2 | using Dashing.Configuration; 3 | using Dashing.Tests.Configuration.SelfReferenceTests.Domain; 4 | 5 | public class TestConfig : BaseConfiguration { 6 | public TestConfig() { 7 | this.AddNamespaceOf(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Dashing/IAnswerProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Collections.Generic; 3 | 4 | public interface IAnswerProvider { 5 | bool GetBooleanAnswer(string question); 6 | 7 | MultipleChoice GetMultipleChoiceAnswer(string question, IEnumerable> choices); 8 | 9 | T GetAnswer(string question) where T : struct; 10 | } 11 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Dashing/Logging/LogLevel.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Logging 2 | { 3 | /// 4 | /// The log level. 5 | /// 6 | #if LIBLOG_PROVIDERS_ONLY 7 | internal 8 | #else 9 | public 10 | #endif 11 | enum LogLevel 12 | { 13 | Trace, 14 | Debug, 15 | Info, 16 | Warn, 17 | Error, 18 | Fatal 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Dashing/SchemaReading/TableDto.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.SchemaReading { 2 | public class TableDto { 3 | public string Schema { get; set; } 4 | 5 | public string Name { get; set; } 6 | 7 | public TemporalType TemporalType { get; set; } 8 | 9 | public string HistorySchema { get; set; } 10 | 11 | public string HistoryName { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Tests/Dashing/DashingConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Tests.Dashing { 2 | using global::Dashing.Configuration; 3 | using global::Dashing.PerformanceTests.Domain; 4 | 5 | internal class DashingConfiguration : BaseConfiguration { 6 | public DashingConfiguration() { 7 | this.AddNamespaceOf(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Dashing/CodeGeneration/IEnumerableAwaiter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CodeGeneration { 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | 5 | internal interface IEnumerableAwaiter : INotifyCompletion { 6 | IEnumerableAwaiter GetAwaiter(); 7 | 8 | bool IsCompleted { get; } 9 | 10 | IEnumerable GetResult(); 11 | } 12 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IBulkUpdateWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | public interface IBulkUpdateWriter { 7 | SqlWriterResult GenerateBulkSql(Action updateAction, IEnumerable>> predicates) 8 | where T : class, new(); 9 | } 10 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Constructor/ClassWithConstructor.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain.Constructor { 2 | using System; 3 | 4 | public class ClassWithConstructor { 5 | public ClassWithConstructor() { 6 | this.CreatedDate = DateTime.UtcNow; 7 | } 8 | 9 | public int Id { get; set; } 10 | 11 | public DateTime CreatedDate { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/SessionDataGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | public class SessionDataGenerator { 6 | public static IEnumerable GetSessions() { 7 | return TestDatabaseGenerator.SessionWrappers.Select(wrapper => new object[] { wrapper }); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Category.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.TestDomain { 2 | using System.Collections.Generic; 3 | 4 | public class Category { 5 | public virtual int CategoryId { get; set; } 6 | 7 | public virtual Category Parent { get; set; } 8 | 9 | public virtual IList Children { get; set; } 10 | 11 | public virtual string Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing/ModelGeneration/IModelGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ModelGeneration { 2 | using System.Collections.Generic; 3 | 4 | using Dashing.Configuration; 5 | using Dashing.SchemaReading; 6 | 7 | internal interface IModelGenerator { 8 | IDictionary GenerateFiles(IEnumerable maps, Database schema, string domainNamespace, IAnswerProvider answerProvider); 9 | } 10 | } -------------------------------------------------------------------------------- /Dashing/SchemaReading/ForeignKeyDto.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.SchemaReading { 2 | public class ForeignKeyDto { 3 | public string TableName { get; set; } 4 | 5 | public string Name { get; set; } 6 | 7 | public string ColumnName { get; set; } 8 | 9 | public string ReferencedTableName { get; set; } 10 | 11 | public string ReferencedColumnName { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing/CodeGeneration/ITrackedEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CodeGeneration { 2 | using System.Collections.Generic; 3 | 4 | public interface ITrackedEntity { 5 | void EnableTracking(); 6 | 7 | void DisableTracking(); 8 | 9 | bool IsTrackingEnabled(); 10 | 11 | IEnumerable GetDirtyProperties(); 12 | 13 | object GetOldValue(string propertyName); 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/AutoNamingDynamicParameters.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using Dapper; 3 | 4 | public class AutoNamingDynamicParameters : DynamicParameters { 5 | private int paramCounter; 6 | 7 | public string Add(object value) { 8 | var name = "@l_" + ++this.paramCounter; 9 | this.Add(name, value); 10 | return name; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IWhereClauseWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | internal interface IWhereClauseWriter { 7 | SelectWriterResult GenerateSql(IEnumerable>> whereClauses, QueryTree rootQueryNode, AutoNamingDynamicParameters parameters, IAliasProvider aliasProvider); 8 | } 9 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory { 2 | using Dashing.Configuration; 3 | using Dashing.Tests.Engine.InMemory.TestDomain; 4 | 5 | public class TestConfiguration : BaseConfiguration { 6 | public TestConfiguration() { 7 | this.AddNamespaceOf(); 8 | this.Setup().Property(p => p.DoNotMap).Ignore(); 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/OneToOne/Category.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain.OneToOne { 2 | using System.Collections.Generic; 3 | 4 | public class Category { 5 | public virtual int CategoryId { get; set; } 6 | 7 | public virtual Category Parent { get; set; } 8 | 9 | public virtual IList Children { get; set; } 10 | 11 | public virtual string Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/IveGotMethods.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public class IveGotMethods { 3 | public int Id { get; set; } 4 | 5 | public string Name { get; set; } 6 | 7 | public override int GetHashCode() { 8 | return 42; 9 | } 10 | 11 | public override bool Equals(object obj) { 12 | return obj == null; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/ILogger.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Collections.Generic; 3 | 4 | public interface ILogger { 5 | void Trace(string message); 6 | 7 | void Trace(string message, params object[] args); 8 | 9 | void Trace(IEnumerable items, string[] columnHeaders = null); 10 | 11 | void Error(string message); 12 | 13 | void Error(string message, params object[] args); 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/ThingWithNullable.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class ThingWithNullable { 3 | public int Id { get; set; } 4 | 5 | public int? Nullable { get; set; } 6 | 7 | public string Name { get; set; } 8 | } 9 | 10 | public class ReferencesThingWithNullable { 11 | public int Id { get; set; } 12 | 13 | public ThingWithNullable Thing { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/Configuration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | using Dashing.Configuration; 3 | using Dashing.IntegrationTests.TestDomain; 4 | using Dashing.IntegrationTests.TestDomain.More; 5 | 6 | class Configuration : BaseConfiguration { 7 | public Configuration() { 8 | this.AddNamespaceOf(); 9 | this.AddNamespaceOf(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Versioned/NonVersioned/VersionedEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.Versioned.NonVersioned { 2 | using System; 3 | 4 | /// 5 | /// Not actually versioned yet but used in the integration tests to add versioning 6 | /// 7 | public class VersionedEntity { 8 | public Guid Id { get; set; } 9 | 10 | public string Name { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/SqlWriterResult.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using Dapper; 3 | 4 | public class SqlWriterResult { 5 | public string Sql { get; internal set; } 6 | 7 | public DynamicParameters Parameters { get; internal set; } 8 | 9 | public SqlWriterResult(string sql, DynamicParameters parameters) { 10 | this.Parameters = parameters; 11 | this.Sql = sql; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing/Logging/LogProviders/LibLogException.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Logging.LogProviders 2 | { 3 | using System; 4 | 5 | public class LibLogException : Exception 6 | { 7 | public LibLogException(string message) 8 | : base(message) 9 | { 10 | } 11 | 12 | public LibLogException(string message, Exception inner) 13 | : base(message, inner) 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Dashing/ReverseEngineering/IReverseEngineeringColumn.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ReverseEngineering { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Dashing.SchemaReading; 6 | 7 | internal interface IReverseEngineeringColumn { 8 | string ForeignKeyTableName { get; set; } 9 | 10 | IDictionary TypeMap { get; set; } 11 | 12 | ColumnDto ColumnSpecification { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/User.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain { 2 | public class User { 3 | public long UserId { get; set; } 4 | 5 | public string Username { get; set; } 6 | 7 | public string EmailAddress { get; set; } 8 | 9 | public string Password { get; set; } 10 | 11 | public bool IsEnabled { get; set; } 12 | 13 | public decimal HeightInMeters { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/OneToOne/Category.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain.OneToOne { 2 | using System.Collections.Generic; 3 | 4 | public class Category { 5 | public virtual int CategoryId { get; set; } 6 | 7 | public virtual Category Parent { get; set; } 8 | 9 | public virtual IList Children { get; set; } 10 | 11 | public virtual string Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing/Migration/StringBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Migration { 2 | using System.Text; 3 | 4 | public static class StringBuilderExtensions { 5 | public static void AppendSql(this StringBuilder builder, string sql) { 6 | builder.Append(sql); 7 | if (builder[builder.Length - 1] != ';') { 8 | builder.Append(";"); 9 | } 10 | 11 | builder.AppendLine(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/Category.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | using System.Collections.Generic; 3 | 4 | public class Category { 5 | public virtual int CategoryId { get; set; } 6 | 7 | public virtual Category Parent { get; set; } 8 | 9 | public virtual IList Children { get; set; } 10 | 11 | public virtual string Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/More/QuestionnaireResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.More { 2 | using System.Collections.Generic; 3 | 4 | public class QuestionnaireResponse { 5 | public long QuestionnaireResponseId { get; set; } 6 | 7 | public Questionnaire Questionnaire { get; set; } 8 | 9 | public Booking Booking { get; set; } 10 | 11 | public IList Responses { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing/CodeGeneration/DelegateProjectionResult.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CodeGeneration { 2 | using System; 3 | 4 | class DelegateProjectionResult { 5 | public DelegateProjectionResult(Type[] types, Func mapper) { 6 | this.Types = types; 7 | this.Mapper = mapper; 8 | } 9 | 10 | public Type[] Types { get; } 11 | 12 | public Func Mapper { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/TestSessionWrapper.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | public class TestSessionWrapper { 3 | public TestSessionWrapper(ISession session) { 4 | this.Session = session; 5 | } 6 | 7 | public ISession Session { get; private set; } 8 | 9 | public string DatabaseName { 10 | get { 11 | return DatabaseInitializer.DatabaseName; 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/Configuration/IConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Configuration { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Dashing.Events; 6 | 7 | public interface IConfiguration { 8 | IEnumerable Maps { get; } 9 | 10 | IMap GetMap(); 11 | 12 | IMap GetMap(Type type); 13 | 14 | bool HasMap(); 15 | 16 | bool HasMap(Type type); 17 | 18 | EventHandlers EventHandlers { get; } 19 | } 20 | } -------------------------------------------------------------------------------- /Dashing/ModelGeneration/DefaultConvention.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ModelGeneration { 2 | using Dashing.Extensions; 3 | 4 | public class DefaultConvention : IConvention { 5 | public string ClassNameForTable(string tableName) { 6 | var className = tableName.Singularize(); 7 | 8 | // capitalise - helps with case-insensitivity of MySql on Windows 9 | return className[0].ToString().ToUpper() + className.Substring(1); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Domain/User.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Domain { 2 | public class User { 3 | public virtual int UserId { get; set; } 4 | 5 | public virtual string Username { get; set; } 6 | 7 | public virtual string EmailAddress { get; set; } 8 | 9 | public virtual string Password { get; set; } 10 | 11 | public virtual bool IsEnabled { get; set; } 12 | 13 | public virtual decimal HeightInMeters { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/AddNamespaceTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration { 2 | using System.Linq; 3 | 4 | using Dashing.Tests.Configuration.AddNamespaceDomain; 5 | 6 | using Xunit; 7 | 8 | public class AddNamespaceTests { 9 | [Fact] 10 | public void AddNamespaceWorksWithConfigurationInSameNamespace() { 11 | var config = new AddNamespaceConfiguration(); 12 | Assert.Equal(2, config.Maps.Count()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/User.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | public class User : IEnableable { 3 | public virtual int UserId { get; set; } 4 | 5 | public virtual string Username { get; set; } 6 | 7 | public virtual string EmailAddress { get; set; } 8 | 9 | public virtual string Password { get; set; } 10 | 11 | public virtual bool IsEnabled { get; set; } 12 | 13 | public virtual decimal HeightInMeters { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/IFetchMany.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | public interface IFetchMany 7 | where TOriginal : class, new() { 8 | ISelectQuery ThenFetch(Expression> selector); 9 | 10 | IFetchMany ThenFetchMany(Expression>> selector); 11 | } 12 | } -------------------------------------------------------------------------------- /Dashing/SchemaReading/IndexDto.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.SchemaReading { 2 | public class IndexDto { 3 | public string TableName { get; set; } 4 | 5 | public string Name { get; set; } 6 | 7 | public string ColumnName { get; set; } 8 | 9 | /// 10 | /// Indicates the position of this column in the index 11 | /// 12 | public int ColumnId { get; set; } 13 | 14 | public bool IsUnique { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Dashing/Configuration/IndexColumnComparer.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Configuration { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | internal class IndexColumnComparer : IEqualityComparer { 6 | public bool Equals(IColumn x, IColumn y) { 7 | return x.Name.Equals(y.Name, StringComparison.OrdinalIgnoreCase); 8 | } 9 | 10 | public int GetHashCode(IColumn obj) { 11 | return obj.Name.GetHashCode(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/ConstantChecker.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System.Linq.Expressions; 3 | 4 | internal class ConstantChecker : BaseExpressionVisitor { 5 | public bool HasParams { get; set; } 6 | 7 | public void Reset() { 8 | this.HasParams = false; 9 | } 10 | 11 | protected override Expression VisitParameter(ParameterExpression p) { 12 | this.HasParams = true; 13 | return p; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Dashing.Cli/NullStatisticsProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Cli { 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Dashing.Configuration; 6 | using Dashing.Migration; 7 | 8 | internal class NullStatisticsProvider : IStatisticsProvider { 9 | public IDictionary GetStatistics(IEnumerable fromMaps) { 10 | return fromMaps.ToDictionary(m => m.Type.Name, m => new Statistics { HasRows = false }); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/SelectWriterResult.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using Dapper; 3 | 4 | public class SelectWriterResult : SqlWriterResult { 5 | public QueryTree MapQueryTree { get; internal set; } 6 | 7 | public int NumberCollectionsFetched { get; set; } 8 | 9 | public SelectWriterResult(string sql, DynamicParameters parameters, QueryTree mapQueryTree) 10 | : base(sql, parameters) { 11 | this.MapQueryTree = mapQueryTree; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Comment.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain { 2 | using System; 3 | 4 | public class Comment { 5 | public Comment() { 6 | this.CommentDate = DateTime.Now; 7 | } 8 | 9 | public long CommentId { get; set; } 10 | 11 | public string Content { get; set; } 12 | 13 | public Post Post { get; set; } 14 | 15 | public User User { get; set; } 16 | 17 | public DateTime CommentDate { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Package Dashing.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set /p version="What is the package version? " 3 | dotnet pack ./Dashing/Dashing.csproj --output ./ --configuration Release /p:PackageVersion=%version% 4 | dotnet pack ./Dashing.Cli/Dashing.Cli.csproj --output ./ --configuration Release /p:PackageVersion=%version% 5 | dotnet pack ./Dashing.Cli/Dashing.Tool.csproj --output ./ --configuration Release /p:PackageVersion=%version% 6 | dotnet pack ./Dashing.Weaver/Dashing.Weaver.csproj --output ./ --configuration Release /p:PackageVersion=%version% 7 | pause -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/User.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | public class User : IEnableable { 3 | public virtual int UserId { get; set; } 4 | 5 | public virtual string Username { get; set; } 6 | 7 | public virtual string EmailAddress { get; set; } 8 | 9 | public virtual string Password { get; set; } 10 | 11 | public virtual bool IsEnabled { get; set; } 12 | 13 | public virtual decimal HeightInMeters { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Foo.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | using System.Collections.Generic; 3 | 4 | public class Foo { 5 | public int FooId { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public bool IsBar { get; set; } 10 | 11 | public bool? IsRah { get; set; } 12 | 13 | public FooType Type { get; set; } 14 | 15 | public IEnumerable Bars { get; set; } 16 | 17 | public IList Ducks { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Dashing.CommandLine/ColorContext.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CommandLine 2 | { 3 | using System; 4 | 5 | public class ColorContext : IDisposable 6 | { 7 | private readonly ConsoleColor original; 8 | 9 | public ColorContext(ConsoleColor color) 10 | { 11 | this.original = Console.ForegroundColor; 12 | Console.ForegroundColor = color; 13 | } 14 | 15 | public void Dispose() 16 | { 17 | Console.ForegroundColor = this.original; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/User.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | public class User { 3 | public virtual int UserId { get; set; } 4 | 5 | public virtual string Username { get; set; } 6 | 7 | public virtual string EmailAddress { get; set; } 8 | 9 | public virtual string Password { get; set; } 10 | 11 | public virtual bool IsEnabled { get; set; } 12 | 13 | public virtual decimal HeightInMeters { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/ReverseEngineering/IEngineer.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ReverseEngineering { 2 | using System.Collections.Generic; 3 | 4 | using Dashing.Configuration; 5 | using Dashing.Engine.Dialects; 6 | using Dashing.SchemaReading; 7 | 8 | public interface IEngineer { 9 | IEnumerable ReverseEngineer( 10 | Database schema, 11 | ISqlDialect sqlDialect, 12 | IEnumerable tablesToIgnore, 13 | IAnswerProvider answerProvider, 14 | bool fixOneToOnes); 15 | } 16 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Domain/Comment.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Domain { 2 | using System; 3 | 4 | public class Comment { 5 | public Comment() { 6 | this.CommentDate = DateTime.Now; 7 | } 8 | 9 | public virtual int CommentId { get; set; } 10 | 11 | public virtual string Content { get; set; } 12 | 13 | public virtual Post Post { get; set; } 14 | 15 | public virtual User User { get; set; } 16 | 17 | public virtual DateTime CommentDate { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Dashing/Migration/TableNameEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Migration { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Dashing.Configuration; 6 | 7 | public class TableNameEqualityComparer : IEqualityComparer { 8 | public bool Equals(IMap x, IMap y) { 9 | return x.Table.Equals(y.Table, StringComparison.OrdinalIgnoreCase); 10 | } 11 | 12 | public int GetHashCode(IMap obj) { 13 | return obj.Table.ToLowerInvariant().GetHashCode(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Dashing/Engine/DDL/ICreateTableWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DDL { 2 | using System.Collections.Generic; 3 | 4 | using Dashing.Configuration; 5 | 6 | public interface ICreateTableWriter { 7 | string CreateTable(IMap map); 8 | 9 | IEnumerable CreateForeignKeys(IMap map); 10 | 11 | IEnumerable CreateForeignKeys(IEnumerable foreignKeys); 12 | 13 | IEnumerable CreateIndexes(IMap map); 14 | 15 | IEnumerable CreateIndexes(IEnumerable indexes); 16 | } 17 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Providers.cs: -------------------------------------------------------------------------------- 1 | namespace PerformanceTest { 2 | internal static class Providers { 3 | public static string Dapper => "Dapper"; 4 | 5 | public static string Dashing => "Dashing"; 6 | 7 | public static string EntityFramework => "EF"; 8 | 9 | public static string ServiceStack => "ServiceStack"; 10 | 11 | public static string SimpleData => "Simple.Data"; 12 | 13 | public static string NHibernate => "NHibernate"; 14 | 15 | public static string LightSpeed => "LightSpeed"; 16 | } 17 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Versioning/VersionedEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain.Versioning { 2 | using System; 3 | 4 | using Dashing.Versioning; 5 | 6 | public class VersionedEntity : IVersionedEntity { 7 | public Guid Id { get; set; } 8 | 9 | public string Name { get; set; } 10 | 11 | public string SessionUser { get; set; } 12 | 13 | public string CreatedBy { get; set; } 14 | 15 | public DateTime SysStartTime { get; set; } 16 | 17 | public DateTime SysEndTime { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Tracking/References.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain.Tracking { 2 | using System; 3 | 4 | public class References { 5 | public int Id { get; set; } 6 | 7 | public GuidPk GuidPk { get; set; } 8 | 9 | public IntPk IntPk { get; set; } 10 | 11 | public StringPk StringPk { get; set; } 12 | 13 | public LongPk LongPk { get; set; } 14 | 15 | public int Foo { get; set; } 16 | 17 | public string Bar { get; set; } 18 | 19 | public Guid? G { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Dashing/Migration/IMigrator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Migration { 2 | using System.Collections.Generic; 3 | 4 | using Dashing.Configuration; 5 | 6 | public interface IMigrator { 7 | string GenerateSqlDiff( 8 | IEnumerable fromMaps, 9 | IEnumerable toMaps, 10 | IAnswerProvider answerProvider, 11 | IEnumerable indexesToIgnore, 12 | IEnumerable tablesToIgnore, 13 | out IEnumerable warnings, 14 | out IEnumerable errors); 15 | } 16 | } -------------------------------------------------------------------------------- /Dashing/Logging/LogProviders/DisposableAction.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Logging.LogProviders 2 | { 3 | using System; 4 | 5 | #if LIBLOG_EXCLUDE_CODE_COVERAGE 6 | [ExcludeFromCodeCoverage] 7 | #endif 8 | internal class DisposableAction : IDisposable 9 | { 10 | private readonly Action _onDispose; 11 | 12 | public DisposableAction(Action onDispose = null) 13 | { 14 | _onDispose = onDispose; 15 | } 16 | 17 | public void Dispose() 18 | { 19 | _onDispose?.Invoke(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Versioned/VersionedEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain.Versioned { 2 | using System; 3 | 4 | using Dashing.Versioning; 5 | public class VersionedEntity : IVersionedEntity { 6 | public Guid Id { get; set; } 7 | 8 | public string Name { get; set; } 9 | 10 | public string SessionUser { get; set; } 11 | 12 | public string CreatedBy { get; set; } 13 | 14 | public DateTime SysStartTime { get; set; } 15 | 16 | public DateTime SysEndTime { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /Dashing/Migration/ColumnKeyValuePairEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Migration { 2 | using System.Collections.Generic; 3 | 4 | using Dashing.Configuration; 5 | 6 | public class ColumnKeyValuePairEqualityComparer : IEqualityComparer> { 7 | public bool Equals(KeyValuePair x, KeyValuePair y) { 8 | return x.Key == y.Key; 9 | } 10 | 11 | public int GetHashCode(KeyValuePair obj) { 12 | return obj.Key.GetHashCode(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/Elements/StringElement.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML.Elements { 2 | using System.Text; 3 | 4 | using Dashing.Engine.Dialects; 5 | 6 | internal sealed class StringElement : ISqlElement { 7 | private readonly string sqlElement; 8 | 9 | public StringElement(string sqlElement) { 10 | this.sqlElement = sqlElement; 11 | } 12 | 13 | public void Append(StringBuilder stringBuilder, ISqlDialect dialect, IAliasProvider aliasProvider) { 14 | stringBuilder.Append(this.sqlElement); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Domain/Blog.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Domain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Blog { 6 | public Blog() { 7 | this.CreateDate = DateTime.Now; 8 | } 9 | 10 | public virtual int BlogId { get; set; } 11 | 12 | public virtual string Title { get; set; } 13 | 14 | public virtual DateTime CreateDate { get; set; } 15 | 16 | public virtual string Description { get; set; } 17 | 18 | public virtual IList Posts { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/ExpressionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory { 2 | using System.Linq.Expressions; 3 | using System.Reflection; 4 | 5 | public static class ExpressionExtensions { 6 | public static string ToDebugString(this Expression expression) { 7 | if (expression == null) 8 | return null; 9 | 10 | var propertyInfo = typeof(Expression).GetProperty("DebugView", BindingFlags.Instance | BindingFlags.NonPublic); 11 | return propertyInfo.GetValue(expression) as string; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/MySqlServerDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | using Dashing.Configuration; 3 | using Dashing.Engine.Dialects; 4 | 5 | using MySql.Data.MySqlClient; 6 | 7 | #if MYSQL 8 | public class MySqlServerDatabase : SqlSessionCreator { 9 | #else 10 | class MySqlServerDatabase : SqlDatabase { 11 | #endif 12 | public MySqlServerDatabase(IConfiguration configuration) 13 | : base(configuration, MySqlClientFactory.Instance, "Server = localhost; Uid=dashingtest;Pwd=SomeDaftPassword;", new MySqlDialect()) { } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/CodeGeneration/ITrackedEntityInspector.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CodeGeneration { 2 | using System; 3 | using System.Linq.Expressions; 4 | 5 | public interface ITrackedEntityInspector : ITrackedEntity { 6 | bool IsPropertyDirty(Expression> propertyExpression); 7 | 8 | TResult GetOldValue(Expression> propertyExpression); 9 | 10 | TResult GetNewValue(Expression> propertyExpression); 11 | 12 | object GetNewValue(string propertyName); 13 | 14 | bool IsDirty(); 15 | } 16 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Blog.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Blog { 6 | public Blog() { 7 | this.CreateDate = DateTime.Now; 8 | this.Posts = new List(); 9 | } 10 | 11 | public long BlogId { get; set; } 12 | 13 | public string Title { get; set; } 14 | 15 | public DateTime CreateDate { get; set; } 16 | 17 | public string Description { get; set; } 18 | 19 | public IList Posts { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Bar.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Bar { 6 | public Bar() { 7 | this.Ducks = new[] { new Duck { Id = 1 } }; 8 | } 9 | 10 | public int Id { get; set; } 11 | 12 | public string Name { get; set; } 13 | 14 | public Foo Foo { get; set; } 15 | 16 | public DateTime CreatedDate { get; set; } 17 | 18 | public int? SomethingOrTother { get; set; } 19 | 20 | public IList Ducks { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/SqlLiteConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | using Dashing.Configuration; 3 | using Dashing.IntegrationTests.TestDomain; 4 | using Dashing.IntegrationTests.TestDomain.More; 5 | 6 | //internal class SqlLiteConfiguration : DefaultConfiguration { 7 | // public SqlLiteConfiguration() 8 | // : base(new ConnectionStringSettings("Default", "Data Source=testdb.db;Version=3;", "System.Data.SQLite")) { 9 | // this.AddNamespaceOf(); 10 | // this.AddNamespaceOf(); 11 | // } 12 | //} 13 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/SqlServerDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | using System.Data.SqlClient; 3 | 4 | using Dashing.Configuration; 5 | using Dashing.Engine.Dialects; 6 | 7 | #if SQLSERVER 8 | public class SqlServerDatabase : SqlDatabase { 9 | #else 10 | class SqlServerDatabase : SqlSessionCreator { 11 | #endif 12 | public SqlServerDatabase(IConfiguration configuration) 13 | : base(configuration, SqlClientFactory.Instance, $"Server=localhost;Trusted_Connection=True;MultipleActiveResultSets=True", new SqlServer2012Dialect()) { } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.Tests/Migration/TableNameEqualityComparerTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.Tests.Migration { 2 | using Dashing.Configuration; 3 | using Dashing.Migration; 4 | using Dashing.Tests.TestDomain; 5 | 6 | using Xunit; 7 | 8 | public class TableNameEqualityComparerTests { 9 | [Fact] 10 | public void IsCaseInsensitive() { 11 | var map1 = new Map() { Table = "posts" }; 12 | var map2 = new Map() { Table = "Posts" }; 13 | var comparer = new TableNameEqualityComparer(); 14 | Assert.True(comparer.Equals(map1, map2)); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Starship.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | public class Starship { 3 | private bool __foo; 4 | 5 | private bool __bar; 6 | 7 | public int Id { get; set; } 8 | 9 | public bool Foo 10 | { 11 | get 12 | { 13 | return this.__foo; 14 | } 15 | 16 | set 17 | { 18 | this.__bar = true; 19 | this.__foo = value; 20 | } 21 | } 22 | 23 | public bool GetBar() { 24 | return this.__bar; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/Blog.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Blog { 6 | public Blog() { 7 | this.Posts = new List(); 8 | } 9 | 10 | public virtual int BlogId { get; set; } 11 | 12 | public virtual string Title { get; set; } 13 | 14 | public virtual DateTime CreateDate { get; set; } 15 | 16 | public virtual string Description { get; set; } 17 | 18 | public virtual IList Posts { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Blog.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Blog { 6 | public Blog() { 7 | this.Posts = new List(); 8 | } 9 | 10 | public virtual int BlogId { get; set; } 11 | 12 | public virtual string Title { get; set; } 13 | 14 | public virtual DateTime CreateDate { get; set; } 15 | 16 | public virtual string Description { get; set; } 17 | 18 | public virtual User Owner { get; set; } 19 | 20 | public virtual IList Posts { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Weaving/NullLogger.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver.Weaving { 2 | using System.Collections.Generic; 3 | 4 | using ILogger = Dashing.ILogger; 5 | 6 | public class NullLogger : ILogger { 7 | public void Trace(string message) { 8 | } 9 | 10 | public void Trace(string message, params object[] args) { 11 | } 12 | 13 | public void Trace(IEnumerable items, string[] columnHeaders = null) { 14 | } 15 | 16 | public void Error(string message) { 17 | } 18 | 19 | public void Error(string message, params object[] args) { 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/AddNamespaceDomain/AddNamespaceConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.AddNamespaceDomain { 2 | using Dashing.Configuration; 3 | 4 | public class AddNamespaceConfiguration : BaseConfiguration { 5 | public AddNamespaceConfiguration() { 6 | this.AddNamespaceOf(); 7 | } 8 | } 9 | 10 | public class Post { 11 | public int PostId { get; set; } 12 | 13 | public string Name { get; set; } 14 | } 15 | 16 | public class User { 17 | public string UserId { get; set; } 18 | 19 | public string Name { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Comment.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Comment { 6 | public Comment() { 7 | this.Likes = new List(); 8 | } 9 | 10 | public virtual int CommentId { get; set; } 11 | 12 | public virtual string Content { get; set; } 13 | 14 | public virtual Post Post { get; set; } 15 | 16 | public virtual User User { get; set; } 17 | 18 | public virtual DateTime CommentDate { get; set; } 19 | 20 | public virtual IList Likes { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Dashing/Engine/DDL/IAlterTableWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DDL { 2 | using Dashing.Configuration; 3 | 4 | public interface IAlterTableWriter { 5 | string AddColumn(params IColumn[] columns); 6 | 7 | string DropColumn(IColumn column); 8 | 9 | string ChangeColumnName(IColumn fromColumn, IColumn toColumn); 10 | 11 | string ModifyColumn(IColumn fromColumn, IColumn toColumn); 12 | 13 | string DropForeignKey(ForeignKey foreignKey); 14 | 15 | string DropIndex(Index index); 16 | 17 | string RenameTable(IMap @from, IMap to); 18 | 19 | string AddSystemVersioning(IMap to); 20 | } 21 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/Blog.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Blog { 6 | public Blog() { 7 | this.Posts = new List(); 8 | } 9 | 10 | public virtual int BlogId { get; set; } 11 | 12 | public virtual string Title { get; set; } 13 | 14 | public virtual DateTime CreateDate { get; set; } 15 | 16 | public virtual string Description { get; set; } 17 | 18 | public virtual User Owner { get; set; } 19 | 20 | public virtual IList Posts { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Dashing/Engine/DapperMapperGeneration/IMultiCollectionMapperGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DapperMapperGeneration { 2 | using System; 3 | 4 | using Dashing.Engine.DML; 5 | 6 | internal interface IMultiCollectionMapperGenerator { 7 | /// 8 | /// Generates a multi collection mapper 9 | /// 10 | /// 11 | /// 12 | /// The mapper, the list of types fetched, the list of collection types 13 | Tuple GenerateMultiCollectionMapper(QueryTree mapQueryTree); 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/Logging/LogProviders/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Logging.LogProviders 2 | { 3 | using System; 4 | using System.Reflection; 5 | 6 | #if LIBLOG_EXCLUDE_CODE_COVERAGE 7 | [ExcludeFromCodeCoverage] 8 | #endif 9 | internal static class TypeExtensions 10 | { 11 | internal static ConstructorInfo GetConstructorPortable(this Type type, params Type[] types) 12 | { 13 | return type.GetConstructor(types); 14 | } 15 | 16 | internal static MethodInfo GetMethod(this Type type, string name, params Type[] types) { 17 | return type.GetTypeInfo().GetMethod(name, types); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/SqlSessionCreatorExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | using System.Reflection; 3 | 4 | using Dashing.Engine; 5 | using Dashing.Engine.Dialects; 6 | 7 | public static class SqlSessionCreatorExtensions { 8 | public static ISqlDialect GetDialect(this SqlDatabase sessionCreator) { 9 | var engine = (SqlEngine)typeof(SqlDatabase) 10 | .GetField("engine", BindingFlags.Instance | BindingFlags.NonPublic) 11 | .GetValue(sessionCreator); 12 | return engine.SqlDialect; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/ISelectWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System.Collections.Generic; 3 | 4 | public interface ISelectWriter { 5 | SelectWriterResult GenerateSql(ProjectedSelectQuery projectedSelectQuery) 6 | where TBase : class, new(); 7 | 8 | SelectWriterResult GenerateSql(SelectQuery selectQuery, AutoNamingDynamicParameters parameters = null, bool enforceAlias = false) where T : class, new(); 9 | 10 | SqlWriterResult GenerateGetSql(TPrimaryKey id); 11 | 12 | SqlWriterResult GenerateGetSql(IEnumerable ids); 13 | } 14 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/Elements/ConstantElement.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML.Elements { 2 | using System.Text; 3 | 4 | using Dashing.Engine.Dialects; 5 | 6 | internal sealed class ConstantElement : ISqlElement { 7 | public string ParamName { get; set; } 8 | 9 | public object Value { get; set; } 10 | 11 | public ConstantElement(string paramName, object value) { 12 | this.ParamName = paramName; 13 | this.Value = value; 14 | } 15 | 16 | public void Append(StringBuilder stringBuilder, ISqlDialect dialect, IAliasProvider aliasProvider) { 17 | stringBuilder.Append(this.ParamName); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/Comment.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Comment { 6 | public Comment() { 7 | this.Likes = new List(); 8 | } 9 | 10 | public virtual int CommentId { get; set; } 11 | 12 | public virtual string Content { get; set; } 13 | 14 | public virtual Post Post { get; set; } 15 | 16 | public virtual User User { get; set; } 17 | 18 | public virtual DateTime CommentDate { get; set; } 19 | 20 | public virtual IList Likes { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Weaving/ColumnDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver.Weaving { 2 | using System.Data; 3 | 4 | using Dashing.Configuration; 5 | 6 | public class ColumnDefinition 7 | { 8 | public string Name { get; set; } 9 | 10 | public string TypeFullName { get; set; } 11 | 12 | public RelationshipType Relationship { get; set; } 13 | 14 | public string RelatedTypePrimarykeyName { get; set; } 15 | 16 | public string DbName { get; set; } 17 | 18 | public bool IsPrimaryKey { get; set; } 19 | 20 | public DbType DbType { get; set; } 21 | 22 | public bool ShouldWeavingInitialiseListInConstructor { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Dashing.Weaving.Sample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net46;net9.0 6 | true 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Dashing/Engine/DapperMapperGeneration/ISingleCollectionMapperGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DapperMapperGeneration { 2 | using System; 3 | 4 | using Dashing.Engine.DML; 5 | 6 | internal interface ISingleCollectionMapperGenerator { 7 | /// 8 | /// Generates a Func for the passed in mapQueryTree 9 | /// 10 | /// The base type of the tree 11 | /// The fetch tree to generate the mapper for 12 | /// A factory for generating mappers 13 | Tuple GenerateCollectionMapper(QueryTree mapQueryTree); 14 | } 15 | } -------------------------------------------------------------------------------- /docs/dapper.md: -------------------------------------------------------------------------------- 1 | --- 2 | queries: true 3 | --- 4 | 5 | # Dapper 6 | 7 | There are occasions where you will want to use Dapper on its own so that you can execute a complicated query or simply maximise 8 | the performance of your database interaction. To take advantage of dapper simply 9 | use the Dapper property on your ISession and then invoke whichever method you need. 10 | This Dapper property, by default, makes use of the open IDbConnection and IDbTransaction 11 | in the session so that you remain in that transaction scope. 12 | 13 | using (var session = database.BeginSession()) { 14 | var stuff = await session.Dapper.QueryAsync("select * from stuff where id = @Id", new { Id = 1 }); 15 | } -------------------------------------------------------------------------------- /Dashing.Tests/MutableConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Dashing.Configuration; 6 | 7 | public class MutableConfiguration : BaseConfiguration { 8 | public new IConfiguration Add() { 9 | return base.Add(); 10 | } 11 | 12 | public new IConfiguration Add(IEnumerable types) { 13 | return base.Add(types); 14 | } 15 | 16 | public IConfiguration AddNamespaceOf() { 17 | return base.AddNamespaceOf(); 18 | } 19 | 20 | public new IMap Setup() { 21 | return base.Setup(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Dashing/Extensions/AssemblyExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Extensions { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | public static class AssemblyExtensions { 8 | public static IEnumerable GetLoadableTypes(this Assembly assembly) { 9 | if (assembly == null) { 10 | throw new ArgumentNullException("assembly"); 11 | } 12 | 13 | try { 14 | return assembly.GetTypes(); 15 | } 16 | catch (ReflectionTypeLoadException e) { 17 | return e.Types.Where(t => t != null); 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /docs/assets/css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | @import "{{ site.theme }}"; 5 | 6 | @media only screen and (min-width: 1140px) { 7 | #main_content { 8 | padding-top: 20px; 9 | min-height: 450px; 10 | } 11 | 12 | #main_content_wrap { 13 | position: relative; 14 | } 15 | 16 | #main_content_wrap nav { 17 | position: fixed; 18 | top: 235px; 19 | right: 50%; 20 | margin-right: 340px; 21 | width: 220px; 22 | } 23 | } 24 | 25 | @media only screen and (max-width: 1139px) { 26 | #main_content_wrap nav { 27 | max-width: 640px; 28 | padding: 20px 10px; 29 | margin: auto; 30 | margin-bottom: -40px; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Dashing/IExecuteSelectQueries.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | public interface ISelectQueryExecutor { 6 | IEnumerable Query(SelectQuery query) where T : class, new(); 7 | 8 | Page QueryPaged(SelectQuery query) where T : class, new(); 9 | 10 | int Count(SelectQuery query) where T : class, new(); 11 | 12 | Task> QueryAsync(SelectQuery query) where T : class, new(); 13 | 14 | Task> QueryPagedAsync(SelectQuery query) where T : class, new(); 15 | 16 | Task CountAsync(SelectQuery query) where T : class, new(); 17 | } 18 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Tests/OuterJoinDisjunctionTransformerTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Tests { 2 | using Dashing.IntegrationTests.Setup; 3 | using Dashing.IntegrationTests.TestDomain; 4 | 5 | using Xunit; 6 | 7 | public class OuterJoinDisjunctionTransformerTests { 8 | [Theory] 9 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 10 | public void OuterJoinDisjunctionWorks(TestSessionWrapper wrapper) { 11 | var posts = wrapper.Session.Query() 12 | .Where(p => p.Blog.Title == "Blog_1" || p.Blog.Title == "Blog_2"); 13 | Assert.NotEmpty(posts); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | --- 2 | configuration: true 3 | --- 4 | 5 | # Configuration 6 | 7 | Dashing is set up to do all of its mapping through Convention over Configuration. However, all of the 8 | conventions can be overridden through the api. 9 | 10 | > There are (a few) times when you have to explicitly configure entities. For example, having multiple foreign key properties of the same type. 11 | 12 | The following sections detail how to perform the various functions: 13 | 14 | * [Configuration Basics](configuration-basics) - how to add entities to your domain and some common modifications 15 | * [Conventions](configuration-conventions) - what conventions are there and how to override 16 | * [Indexes](Indexes) - how to add Indexes -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/Comment.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Comment { 6 | public Comment() { 7 | this.Likes = new List(); 8 | } 9 | 10 | public virtual int CommentId { get; set; } 11 | 12 | public virtual string Content { get; set; } 13 | 14 | public virtual Post Post { get; set; } 15 | 16 | public virtual User User { get; set; } 17 | 18 | public virtual DateTime CommentDate { get; set; } 19 | 20 | public virtual DateTime? DeletedDate { get; set; } 21 | 22 | public virtual IList Likes { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Dashing.Weaver/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver { 2 | using Dashing.Weaver.Commands; 3 | 4 | using McMaster.Extensions.CommandLineUtils; 5 | 6 | public class Program { 7 | public static int Main(string[] args) { 8 | var app = new CommandLineApplication { 9 | Name = "dashing-weaver", 10 | Description = "Weaves domain classes in order to support Dashing functionality" 11 | }; 12 | app.HelpOption(inherited: true); 13 | app.UseExtractConfigs(); 14 | app.UseWeave(); 15 | return app.Execute(args); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Weaving/TypeDefinitionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver.Weaving { 2 | using System; 3 | using System.Linq; 4 | 5 | using Mono.Cecil; 6 | 7 | public static class TypeDefinitionExtensions { 8 | public static bool ImplementsInterface(this TypeDefinition typeDefinition, Type interfaceType) { 9 | if (typeDefinition.Interfaces.Any(i => i.InterfaceType.FullName == interfaceType.FullName)) { 10 | return true; 11 | } 12 | 13 | if (typeDefinition.BaseType.FullName == typeof(object).FullName) { 14 | return false; 15 | } 16 | 17 | return typeDefinition.BaseType.Resolve().ImplementsInterface(interfaceType); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Dashing/Engine/InMemory/InMemoryDbTransaction.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.InMemory { 2 | using System.Data; 3 | using System.Data.Common; 4 | 5 | internal class InMemoryDbTransaction : DbTransaction { 6 | public InMemoryDbTransaction(DbConnection connection, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) { 7 | this.DbConnection = connection; 8 | this.IsolationLevel = isolationLevel; 9 | } 10 | 11 | public override void Commit() { 12 | 13 | } 14 | 15 | public override void Rollback() { 16 | } 17 | 18 | protected override DbConnection DbConnection { get; } 19 | 20 | public override IsolationLevel IsolationLevel { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /Dashing/Engine/Dialects/SqlServer2012Dialect.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.Dialects { 2 | using System.Text; 3 | 4 | public class SqlServer2012Dialect : SqlServerDialect { 5 | public override void ApplySkipTake(StringBuilder sql, StringBuilder orderClause, int take, int skip) { 6 | if (orderClause.Length == 0) { 7 | // Sql Server 2012 only supports offset with an order by clause 8 | base.ApplySkipTake(sql, orderClause, take, skip); 9 | return; 10 | } 11 | 12 | sql.Append(" offset " + (skip > 0 ? "@skip" : "0") + " rows"); 13 | 14 | if (take > 0) { 15 | sql.Append(" fetch next @take rows only"); 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/IOrderClauseWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System; 3 | 4 | using Dashing.Configuration; 5 | 6 | internal interface IOrderClauseWriter { 7 | string GetOrderClause( 8 | OrderClause clause, 9 | QueryTree rootQueryNode, 10 | IAliasProvider aliasProvider, 11 | out bool isRootPrimaryKeyClause); 12 | 13 | string GetOrderClause( 14 | OrderClause clause, 15 | QueryTree rootQueryNode, 16 | IAliasProvider aliasProvider, 17 | Func aliasRewriter, 18 | Func nameRewriter, 19 | out bool isRootPrimaryKeyClause); 20 | } 21 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/ReverseEngineer/Sandbox.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.ReverseEngineer { 2 | public class Sandbox { 3 | private const string ConnectionString = "Server=localhost;Database=mercury_dev;Uid=root;Password=treatme123;Allow User Variables=true"; 4 | 5 | private const string ProviderName = "MySql.Data.MySqlClient"; 6 | 7 | ////[Fact] 8 | ////public void Test() 9 | ////{ 10 | //// var engineer = new Dashing.Configuration.ReverseEngineer.Engineer(); 11 | //// var schemaReader = new DatabaseSchemaReader.DatabaseReader(ConnectionString, DatabaseSchemaReader.DataSchema.SqlType.MySql); 12 | //// var maps = engineer.ReverseEngineer(schemaReader); 13 | ////} 14 | } 15 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Domain/Whopper.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample.Domain { 2 | using System.Collections.Generic; 3 | 4 | public class Whopper { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | private IEnumerable __ducks; 10 | 11 | private string filling; 12 | 13 | public IEnumerable Ducks 14 | { 15 | get 16 | { 17 | return this.__ducks; 18 | } 19 | 20 | set 21 | { 22 | this.filling = "Burger"; 23 | this.__ducks = value; 24 | } 25 | } 26 | 27 | public string GetFilling() { 28 | return this.filling; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Dashing/Configuration/RelationshipType.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Configuration { 2 | /// 3 | /// The relationship type. 4 | /// 5 | public enum RelationshipType { 6 | /// 7 | /// The none. 8 | /// 9 | None, 10 | 11 | /// 12 | /// The one to many. 13 | /// 14 | OneToMany, 15 | 16 | /// 17 | /// The many to one. 18 | /// 19 | ManyToOne, 20 | 21 | /// 22 | /// The many to many. 23 | /// 24 | ManyToMany, 25 | 26 | /// 27 | /// One to One 28 | /// 29 | OneToOne 30 | } 31 | } -------------------------------------------------------------------------------- /Dashing.Cli/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Dashing.Cli": { 4 | "commandName": "Project", 5 | "commandLineArgs": "script" 6 | }, 7 | "script": { 8 | "commandName": "Project", 9 | "commandLineArgs": "script -a \"C:\\Repos\\dashingcoretest\\bin\\Debug\\netcoreapp2.0\\dashingcoretest.dll\" -t \"dashingcoretest.DashingConfiguration\" -c \"Data Source=.;Initial Catalog=dashingcoretest;Integrated Security=True;\"" 10 | }, 11 | "migrate": { 12 | "commandName": "Project", 13 | "commandLineArgs": "migrate -a \"C:\\Repos\\dashing\\Dashing.Tests\\bin\\Debug\\net46\\Dashing.Tests.dll\" -t \"Dashing.Tools.Tests.CustomConfig\" -c \"Data Source=.;Initial Catalog=dashingclitest;Integrated Security=True;\"" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Sample/Config.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Sample { 2 | using Dashing.Configuration; 3 | using Dashing.Weaving.Sample.Domain; 4 | using Dashing.Weaving.Sample.Domain.Tracking; 5 | using Dashing.Weaving.Sample2; 6 | 7 | public class Config : BaseConfiguration { 8 | public Config() { 9 | this.AddNamespaceOf(); 10 | this.AddNamespaceOf(); 11 | this.Add(); 12 | this.Setup() 13 | .Property(f => f.Ducks) 14 | .ShouldWeavingInitialiseListInConstructor = true; 15 | this.Setup() 16 | .Property(w => w.Ducks) 17 | .ShouldWeavingInitialiseListInConstructor = true; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Dashing/SchemaReading/ColumnDto.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.SchemaReading { 2 | using System.Data; 3 | 4 | public class ColumnDto { 5 | public string TableName { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public string DbTypeName { get; set; } 10 | 11 | public DbType? DbType { private get; set; } 12 | 13 | public int? Precision { get; set; } 14 | 15 | public int? Scale { get; set; } 16 | 17 | public bool? MaxLength { get; set; } 18 | 19 | public int? Length { get; set; } 20 | 21 | public string Default { get; set; } 22 | 23 | public bool IsNullable { get; set; } 24 | 25 | public bool IsPrimaryKey { get; set; } 26 | 27 | public bool IsAutoGenerated { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/TestDomain/Post.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.TestDomain { 2 | using System.Collections.Generic; 3 | 4 | public class Post { 5 | public Post() { 6 | this.Comments = new List(); 7 | this.Tags = new List(); 8 | } 9 | 10 | public long PostId { get; set; } 11 | 12 | public string Title { get; set; } 13 | 14 | public string Content { get; set; } 15 | 16 | public decimal Rating { get; set; } 17 | 18 | public User Author { get; set; } 19 | 20 | public Blog Blog { get; set; } 21 | 22 | public IList Comments { get; set; } 23 | 24 | public IList Tags { get; set; } 25 | 26 | public bool DoNotMap { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /Dashing/SchemaReading/SchemaReaderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.SchemaReading { 2 | using System; 3 | 4 | public class SchemaReaderFactory { 5 | public ISchemaReader GetSchemaReader(string providerName) { 6 | if (string.IsNullOrWhiteSpace(providerName)) { 7 | throw new ArgumentNullException("providerName"); 8 | } 9 | 10 | switch (providerName) { 11 | case "System.Data.SqlClient": 12 | return new SqlServerSchemaReader(); 13 | 14 | case "MySql.Data.MySqlClient": 15 | return new MySqlServerSchemaReader(); 16 | } 17 | 18 | throw new NotSupportedException(string.Format("dbm does not support the {0} provider", providerName)); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Dashing/IProjectedSelectQueryExecutor.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | public interface IProjectedSelectQueryExecutor : ISelectQueryExecutor { 6 | IEnumerable Query(ProjectedSelectQuery query) 7 | where TBase : class, new(); 8 | 9 | Page QueryPaged(ProjectedSelectQuery query) 10 | where TBase : class, new(); 11 | 12 | Task> QueryAsync(ProjectedSelectQuery query) 13 | where TBase : class, new(); 14 | 15 | Task> QueryPagedAsync(ProjectedSelectQuery query) 16 | where TBase : class, new(); 17 | } 18 | } -------------------------------------------------------------------------------- /Dashing/IEnumerableSelectQuery.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | public interface IEnumerableSelectQuery : IEnumerable { 6 | T First(); 7 | 8 | T FirstOrDefault(); 9 | 10 | T Single(); 11 | 12 | T SingleOrDefault(); 13 | 14 | T Last(); 15 | 16 | T LastOrDefault(); 17 | 18 | Page AsPaged(int skip, int take); 19 | 20 | Task> ToListAsync(); 21 | 22 | Task ToArrayAsync(); 23 | 24 | Task FirstAsync(); 25 | 26 | Task FirstOrDefaultAsync(); 27 | 28 | Task SingleAsync(); 29 | 30 | Task SingleOrDefaultAsync(); 31 | 32 | Task LastAsync(); 33 | 34 | Task LastOrDefaultAsync(); 35 | 36 | Task> AsPagedAsync(int skip, int take); 37 | } 38 | } -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/SelfReferenceTests/Domain/Post.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration.SelfReferenceTests.Domain { 2 | using System.Collections.Generic; 3 | 4 | public class Post { 5 | public Post() { 6 | this.Comments = new List(); 7 | this.Tags = new List(); 8 | } 9 | 10 | public virtual int PostId { get; set; } 11 | 12 | public virtual string Title { get; set; } 13 | 14 | public virtual string Content { get; set; } 15 | 16 | public virtual decimal Rating { get; set; } 17 | 18 | public virtual User Author { get; set; } 19 | 20 | public virtual Blog Blog { get; set; } 21 | 22 | public virtual IList Comments { get; set; } 23 | 24 | public virtual IList Tags { get; set; } 25 | 26 | public virtual bool DoNotMap { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /Dashing/Page.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Collections.Generic; 3 | 4 | /// 5 | /// Represents a page of results of a query 6 | /// 7 | /// 8 | public class Page { 9 | /// 10 | /// The total number of results. 11 | /// 12 | public int TotalResults { get; set; } 13 | 14 | /// 15 | /// The number of results skipped over. 16 | /// 17 | public int Skipped { get; set; } 18 | 19 | /// 20 | /// The number of results taken. 21 | /// 22 | public int Taken { get; set; } 23 | 24 | /// 25 | /// The enumerable of items in this page. 26 | /// 27 | public IEnumerable Items { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /Dashing.Tests/CustomConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tools.Tests { 2 | using System; 3 | 4 | using Dashing.Configuration; 5 | using Dashing.Tests.TestDomain; 6 | using Dashing.Tests.TestDomain.Constructor; 7 | 8 | public class CustomConfig : BaseConfiguration, ISeeder { 9 | public CustomConfig() { 10 | this.AddNamespaceOf(); 11 | } 12 | 13 | public void Seed(ISession session) { 14 | var blog = new Blog { Title = "My Blog", CreateDate = DateTime.Now }; 15 | session.InsertOrUpdate(blog); 16 | 17 | var user = new User { Username = "Mark", EmailAddress = "maj@113.com" }; 18 | session.InsertOrUpdate(user); 19 | } 20 | } 21 | 22 | public class ClassWithConstructorConfig : BaseConfiguration { 23 | public ClassWithConstructorConfig() { 24 | this.Add(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Test.ini: -------------------------------------------------------------------------------- 1 | [Database] 2 | ConnectionString = Data Source=.;Initial Catalog=ora;Integrated Security=True; 3 | ProviderName = System.Data.SqlClient 4 | 5 | [Dashing] 6 | ; The path to the dll that contains your Dashing Configuration 7 | PathToDll = "..\..\..\..\ora\ORA.Database\bin\Debug\ORA.Database.dll" 8 | 9 | ; The name (namespace and class name) of the Configuration for this Project 10 | ConfigurationName = ORA.Database.DashingConfiguration 11 | 12 | ; The location where the dbmanager will save scripts/source files by default if not specified 13 | ; by the console arguments 14 | DefaultSavePath = . 15 | 16 | [ReverseEngineer] 17 | ; Specify the namespace that you'd like your classes to be generated under 18 | GeneratedNamespace = Dashing.ReverseEngineer 19 | ExtraPluralizationWords = Course,Courses|QuestionnaireCourse,QuestionnaireCourses|FlightDetails,FlightDetails|SeasonPrevious,SeasonPrevious 20 | IndexesToIgnore = -------------------------------------------------------------------------------- /Dashing/CodeGeneration/FetchCollectionAwaiter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CodeGeneration { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Runtime.CompilerServices; 5 | 6 | internal class FetchCollectionAwaiter : IEnumerableAwaiter { 7 | public TaskAwaiter> Awaiter { get; set; } 8 | 9 | public IEnumerable Results { get; set; } 10 | 11 | public IEnumerableAwaiter GetAwaiter() { 12 | return this; 13 | } 14 | 15 | public bool IsCompleted 16 | { 17 | get 18 | { 19 | return this.Awaiter.IsCompleted; 20 | } 21 | } 22 | 23 | public IEnumerable GetResult() { 24 | return this.Results; 25 | } 26 | 27 | public void OnCompleted(Action continuation) { 28 | this.Awaiter.OnCompleted(continuation); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Dashing.Weaver": { 4 | "commandName": "Project" 5 | }, 6 | "TestExtractConfigs": { 7 | "commandName": "Project", 8 | "commandLineArgs": "extractconfigs -p \"C:\\Users\\MarkJerzykowski\\source\\repos\\ConsoleApp3\\ConsoleApp3\\bin\\Debug\\net9.0\\ConsoleApp3.dll\" -t \"DashingConfiguration\"" 9 | }, 10 | "TestWeave": { 11 | "commandName": "Project", 12 | "commandLineArgs": "weave -p \"C:\\Users\\MarkJerzykowski\\source\\repos\\ConsoleApp3\\ConsoleApp3\\bin\\Debug\\net9.0\\ConsoleApp3.dll\" -t \"ConsoleApp3.Domain.DashingConfiguration\"" 13 | }, 14 | "weave versioned": { 15 | "commandName": "Project", 16 | "commandLineArgs": "weave -p \"C:\\Repos\\dashing\\Dashing.IntegrationTests\\bin\\Debug\\net46\\Dashing.IntegrationTests.dll\" -t \"Dashing.IntegrationTests.TestDomain.Versioned.VersionedConfiguration\"" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Dashing.Weaver/Weaving/ModuleDefinitionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaver.Weaving { 2 | using System.Linq; 3 | 4 | using Mono.Cecil; 5 | 6 | public static class ModuleDefinitionExtensions { 7 | public static TypeDefinition GetTypeDefFromFullName(this ModuleDefinition moduleDefinition, string typeFullName) { 8 | TypeDefinition typeDef; 9 | if (typeFullName.Contains('+')) { 10 | var types = typeFullName.Split('+'); 11 | typeDef = moduleDefinition.Types.Single(t => t.FullName == types.First()); 12 | for (var i = 1; i < types.Length; i++) { 13 | typeDef = typeDef.NestedTypes.Single(t => t.Name == types.ElementAt(i)); 14 | } 15 | } 16 | else { 17 | typeDef = moduleDefinition.Types.Single(t => t.FullName == typeFullName); 18 | } 19 | 20 | return typeDef; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Dashing/Engine/DDL/DropTableWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DDL { 2 | using System; 3 | using System.Text; 4 | 5 | using Dashing.Configuration; 6 | using Dashing.Engine.Dialects; 7 | 8 | public class DropTableWriter : IDropTableWriter { 9 | private readonly ISqlDialect dialect; 10 | 11 | public DropTableWriter(ISqlDialect dialect) { 12 | if (dialect == null) { 13 | throw new ArgumentNullException("dialect"); 14 | } 15 | 16 | this.dialect = dialect; 17 | } 18 | 19 | public string DropTable(IMap map) { 20 | var sql = new StringBuilder(); 21 | sql.Append("drop table "); 22 | this.dialect.AppendQuotedTableName(sql, map); 23 | return sql.ToString(); 24 | } 25 | 26 | public string DropTableIfExists(IMap map) { 27 | return this.dialect.WriteDropTableIfExists(map.Table); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /docs/seeding.md: -------------------------------------------------------------------------------- 1 | It's a common requirement that databases have a set of pre-seeded data in them for general use e.g. a table of countries 2 | or currency codes. 3 | 4 | Regardless of what you're seeding you simply need to implement ISeeder. This can then be executed using dash 5 | 6 | public class DashingConfiguration : DefaultConfiguration, ISeeder { 7 | public DashingConfiguration() 8 | : base(ConfigurationManager.ConnectionStrings["DefaultDb"]) { 9 | this.AddNamespaceOf(); 10 | } 11 | 12 | public void Seed(ISession session) { 13 | // insert some data here 14 | } 15 | } 16 | 17 | In general, you'll want to make sure that this method is idempotent i.e. if you create some data in here it's not created 18 | every time Seed is called. This function is called by the [dbm](Dbm) tool every time 19 | the database is migrated. 20 | 21 | You may want to make use of the `InsertOrUpdate` method on the ISession -------------------------------------------------------------------------------- /Dashing/ISession.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System; 3 | 4 | using Dashing.Configuration; 5 | 6 | public partial interface ISession : IDisposable { 7 | /// 8 | /// Gets the Configuration object for this Session 9 | /// 10 | IConfiguration Configuration { get; } 11 | 12 | /// 13 | /// Use Dapper functions in the context of this Session 14 | /// 15 | IDapper Dapper { get; } 16 | 17 | /// 18 | /// Completes the session, effectively calling commit on the underlying transaction 19 | /// 20 | void Complete(); 21 | 22 | /// 23 | /// Rejects the session, effectively rolling back the underlying transaction 24 | /// 25 | /// This will rollback the transaction at the point the Session is disposed 26 | void Reject(); 27 | } 28 | } -------------------------------------------------------------------------------- /Dashing.Tests/TestDomain/Post.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.TestDomain { 2 | using System.Collections.Generic; 3 | 4 | public class Post { 5 | public Post() { 6 | this.Comments = new List(); 7 | this.Tags = new List(); 8 | } 9 | 10 | public virtual int PostId { get; set; } 11 | 12 | public virtual string Title { get; set; } 13 | 14 | public virtual string Content { get; set; } 15 | 16 | public virtual decimal Rating { get; set; } 17 | 18 | public virtual User Author { get; set; } 19 | 20 | public virtual Blog Blog { get; set; } 21 | 22 | public virtual IList Comments { get; set; } 23 | 24 | public virtual IList Tags { get; set; } 25 | 26 | public virtual IList DeletedTags { get; set; } 27 | 28 | public virtual IList YetMoreTags { get; set; } 29 | 30 | public virtual bool DoNotMap { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/Elements/ColumnElement.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML.Elements { 2 | using System.Text; 3 | 4 | using Dashing.Engine.Dialects; 5 | 6 | internal sealed class ColumnElement : ISqlElement { 7 | private readonly string columnName; 8 | 9 | public ColumnElement(BaseQueryNode queryNode, string columnName, bool isRoot) { 10 | this.QueryNode = queryNode; 11 | this.columnName = columnName; 12 | this.IsRoot = isRoot; 13 | } 14 | 15 | public bool IsRoot { get; set; } 16 | 17 | public BaseQueryNode QueryNode { get; set; } 18 | 19 | public void Append(StringBuilder stringBuilder, ISqlDialect dialect, IAliasProvider aliasProvider) { 20 | if (this.QueryNode != null) { 21 | stringBuilder.Append(aliasProvider.GetAlias(this.QueryNode)).Append("."); 22 | } 23 | 24 | dialect.AppendQuotedName(stringBuilder, this.columnName); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Dashing/Configuration/IMapper.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Configuration { 2 | using System; 3 | 4 | /// 5 | /// The Mapper interface. 6 | /// 7 | public interface IMapper { 8 | /// 9 | /// Return a typed map for the typeparameter specified 10 | /// 11 | /// Type to be mapped 12 | /// Configuration that the map belongs to 13 | /// Map for the type 14 | IMap MapFor(IConfiguration configuration); 15 | 16 | /// 17 | /// Return a generic map for the type specified 18 | /// 19 | /// Type to be mapped 20 | /// Configuration that the map belongs to 21 | /// Map for the type 22 | IMap MapFor(Type type, IConfiguration configuration); 23 | } 24 | } -------------------------------------------------------------------------------- /NuGet/dashing-cli.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dashing.Cli 5 | $version$ 6 | Dashing Cli 7 | Polylytics 8 | Polylytics 9 | https://github.com/Polylytics/dashing 10 | http://polylytics.com/dashing/dashing-icon.png 11 | false 12 | Dashing.Cli is a command line tool for migrating database schemas 13 | © Polylytics Limited, 2018 14 | en-GB 15 | dashing dapper orm sql mini-orm 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Domain/Post.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Domain { 2 | using System.Collections.Generic; 3 | 4 | //[Alias("Posts")] 5 | public class Post { 6 | public Post() { 7 | this.Comments = new List(); 8 | this.Tags = new List(); 9 | } 10 | 11 | //[AutoIncrement] 12 | //[PrimaryKey] 13 | public virtual int PostId { get; set; } 14 | 15 | public virtual string Title { get; set; } 16 | 17 | public virtual string Content { get; set; } 18 | 19 | public virtual decimal Rating { get; set; } 20 | 21 | //[Ignore] 22 | public virtual User Author { get; set; } 23 | 24 | //[Ignore] 25 | public virtual Blog Blog { get; set; } 26 | 27 | //[Ignore] 28 | public virtual IList Comments { get; set; } 29 | 30 | //[Ignore] 31 | public virtual IList Tags { get; set; } 32 | 33 | public virtual bool DoNotMap { get; set; } 34 | } 35 | } -------------------------------------------------------------------------------- /Dashing.Tests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Dashing.Weaving.Tests/WeavingTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Tests { 2 | using Dashing.Weaving.Sample.Domain; 3 | 4 | using Xunit; 5 | 6 | public class WeavingTests { 7 | [Fact] 8 | public void NullCollectionDoesNotGetInstantiatedInConstructor() { 9 | var foo = new Foo(); 10 | Assert.Null(foo.Bars); 11 | } 12 | 13 | [Fact] 14 | public void NullCollectionGetsInstantiatedInConstructor() 15 | { 16 | var foo = new Foo(); 17 | Assert.NotNull(foo.Ducks); 18 | } 19 | 20 | [Fact] 21 | public void AlreadyInstantiatedCollectionDoesNotGetInstantiatedInConstructor() { 22 | var bar = new Bar(); 23 | Assert.NotEmpty(bar.Ducks); 24 | } 25 | 26 | [Fact] 27 | public void NonAutoOneToManyGetsInstantiated() { 28 | var whopper = new Whopper(); 29 | Assert.NotNull(whopper.Ducks); 30 | Assert.Equal("Burger", whopper.GetFilling()); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /docs/migrations.md: -------------------------------------------------------------------------------- 1 | # Migrations 2 | 3 | Migrations are done using the dash tool including in Dashing.Cli (see [Getting Started](start)) 4 | This tool lets you specify a database and the configuration and the tool will read the schema of 5 | that database and then generate a script to upgrade it to the configuration you've specified. 6 | 7 | To get help on running the dash tool simply run 8 | 9 | (dotnet) dash --help 10 | 11 | You'll see that there are 4 commands available within dash at the moment: 12 | 13 | * addweave - see [Getting Started](start) for information on this. 14 | * script - generates a script that will update the specified database to match your IConfiguration 15 | * migrate - will execute the script that is generated from script 16 | * seed - will execute a function that lets you auto-populate data. 17 | 18 | For help on using each function type 19 | 20 | (dotnet) dash --help 21 | 22 | > Note, that blindly running migrate on a production database properly isn't the best idea. We usualy do a script first, check it and then run migrate. -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Test.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests { 2 | using System; 3 | 4 | internal class Test { 5 | public Test(string provider, string name, Action func, string method = null) { 6 | this.Provider = provider; 7 | this.TestName = name; 8 | this.TestFunc = func; 9 | this.Method = method; 10 | } 11 | 12 | /// Prevents 'return value of pure method is not used' warnings 13 | public Test(string provider, string name, Func func, string method = null) 14 | : this(provider, name, i => { var forceEvaluation = func(i) != null; }, method) { 15 | } 16 | 17 | public string Provider { get; private set; } 18 | 19 | public string Method { get; private set; } 20 | 21 | public string TestName { get; private set; } 22 | 23 | public Action TestFunc { get; private set; } 24 | 25 | public string FriendlyName => this.Method == null ? this.Provider : $"{this.Provider} ({this.Method})"; 26 | } 27 | } -------------------------------------------------------------------------------- /Dashing/Engine/InMemory/InMemoryKeyGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.InMemory { 2 | using System; 3 | 4 | public class InMemoryKeyGenerator { 5 | private long latest; 6 | 7 | public object GetNextPrimaryKey() { 8 | if (typeof(TPrimaryKey) == typeof(Guid)) { 9 | return Guid.NewGuid(); 10 | } 11 | if (typeof(TPrimaryKey) == typeof(int)) { 12 | this.latest++; 13 | return (int)this.latest; 14 | } 15 | if (typeof(TPrimaryKey) == typeof(short)) { 16 | this.latest++; 17 | return (short)this.latest; 18 | } 19 | if (typeof(TPrimaryKey) == typeof(long)) { 20 | this.latest++; 21 | return this.latest; 22 | } 23 | if (typeof(TPrimaryKey) == typeof(byte)) { 24 | this.latest++; 25 | return (byte)this.latest; 26 | } 27 | throw new Exception("Unknown Primary Key Type"); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Tests/SelectTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Tests { 2 | using System.Linq; 3 | 4 | using Dashing.IntegrationTests.Setup; 5 | using Dashing.IntegrationTests.TestDomain; 6 | 7 | using Xunit; 8 | 9 | public class SelectTests { 10 | [Theory] 11 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 12 | public void WhereEnumerableWorks(TestSessionWrapper wrapper) { 13 | var ids = new long[] { 1, 2, 3 }; 14 | var posts = wrapper.Session.Query().Where(p => ids.Contains(p.PostId)).ToList(); 15 | Assert.Equal(3, posts.Count); 16 | } 17 | 18 | [Theory] 19 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 20 | public void WhereAnyWorks(TestSessionWrapper wrapper) { 21 | var posts = wrapper.Session.Query().Where(p => p.Comments.Any(c => c.Content == "Comment_1")).ToList(); 22 | Assert.Single(posts); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Dashing/Extensions/DictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Extensions { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public static class DictionaryExtensions { 6 | public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func valueCreator) { 7 | // if you change the name of valueCreator I'd do a Find in Solution ;-) 8 | TValue value; 9 | if (!dictionary.TryGetValue(key, out value)) { 10 | value = valueCreator(); 11 | dictionary.Add(key, value); 12 | } 13 | 14 | return value; 15 | } 16 | 17 | public static TValue GetOrAdd(this IDictionary dictionary, TKey key) where TValue : new() { 18 | return dictionary.GetOrAdd(key, () => new TValue()); 19 | } 20 | 21 | public static TValue GetOrAdd(this IDictionary dictionary, TKey key, TValue value) { 22 | return dictionary.GetOrAdd(key, () => value); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/InMemory/TestDomain/Post.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.InMemory.TestDomain { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | public class Post { 6 | public Post() { 7 | this.Comments = new List(); 8 | this.Tags = new List(); 9 | } 10 | 11 | public virtual int PostId { get; set; } 12 | 13 | public virtual string Title { get; set; } 14 | 15 | public virtual string Content { get; set; } 16 | 17 | public virtual decimal Rating { get; set; } 18 | 19 | public virtual User Author { get; set; } 20 | 21 | public virtual Blog Blog { get; set; } 22 | 23 | public virtual IList Comments { get; set; } 24 | 25 | public virtual IList Tags { get; set; } 26 | 27 | public virtual IList DeletedTags { get; set; } 28 | 29 | public virtual IList YetMoreTags { get; set; } 30 | 31 | public virtual bool DoNotMap { get; set; } 32 | 33 | public DateTime? DeletedDate { get; set; } 34 | } 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Polylytics 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Dashing/Engine/DML/WriterQueryCacheKey.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System; 3 | 4 | using Dashing.Configuration; 5 | 6 | public class WriterQueryCacheKey { 7 | public WriterQueryCacheKey(IConfiguration configuration, Type type) { 8 | this.Configuration = configuration; 9 | this.Type = type; 10 | } 11 | 12 | public IConfiguration Configuration { get; private set; } 13 | 14 | public Type Type { get; private set; } 15 | 16 | public override int GetHashCode() { 17 | unchecked { 18 | return this.Configuration.GetHashCode() * this.Type.GetHashCode(); 19 | } 20 | } 21 | 22 | public override bool Equals(object obj) { 23 | if (obj == null) { 24 | return false; 25 | } 26 | 27 | var otherKey = obj as WriterQueryCacheKey; 28 | if (otherKey == null) { 29 | return false; 30 | } 31 | 32 | return Object.ReferenceEquals(this.Configuration, otherKey.Configuration) && this.Type == otherKey.Type; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Dashing.Cli/DbProviderFactoryFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Cli { 2 | using System; 3 | using System.Data.Common; 4 | using System.Data.SqlClient; 5 | 6 | using MySql.Data.MySqlClient; 7 | 8 | public class DbProviderFactoryFactory { 9 | public DbProviderFactory Create(string providerName, string connectionString) { 10 | if (string.IsNullOrWhiteSpace(providerName)) 11 | { 12 | throw new ArgumentNullException("providerName"); 13 | } 14 | 15 | if (string.IsNullOrWhiteSpace(connectionString)) 16 | { 17 | throw new ArgumentNullException("connectionString"); 18 | } 19 | 20 | switch (providerName) 21 | { 22 | case "System.Data.SqlClient": 23 | return SqlClientFactory.Instance; 24 | 25 | case "MySql.Data.MySqlClient": 26 | return MySqlClientFactory.Instance; 27 | 28 | default: 29 | throw new NotImplementedException("Sorry, we don't support the \"" + providerName + "\" provider just yet"); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Dashing/OrderClause.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.ComponentModel; 3 | using System.Linq.Expressions; 4 | 5 | /// 6 | /// The order clause. 7 | /// 8 | /// 9 | /// 10 | public class OrderClause { 11 | /// 12 | /// Gets the expression. 13 | /// 14 | public Expression Expression { get; private set; } 15 | 16 | /// 17 | /// Gets the direction. 18 | /// 19 | public ListSortDirection Direction { get; internal set; } 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// 25 | /// The expression. 26 | /// 27 | /// 28 | /// The direction. 29 | /// 30 | public OrderClause(Expression expression, ListSortDirection direction) { 31 | this.Expression = expression; 32 | this.Direction = direction; 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /docs/queries.md: -------------------------------------------------------------------------------- 1 | --- 2 | queries: true 3 | --- 4 | 5 | # Manipulating Data 6 | 7 | Dashing attempts to provide an intuitive api for performing most of the common sql functions that you would expect to be able to perform 8 | e.g. selecting data as objects from the database, updating or deleting that data, inserting new data. 9 | 10 | We like to think of Dashing as a tool for easily performing sql functions, as opposed to a complete abstraction of the database, 11 | and as such you can also perform bulk updates to your database. 12 | 13 | The following sections detail how to perform the various functions: 14 | 15 | * [Sessions](sessions) - how to set up a connection to the database and manage transactions 16 | * [Getting data out](selecting-data) - how to SELECT data 17 | * [Saving and deleting entities](saving-and-deleting) - how to INSERT, UPDATE, DELETE 18 | * [Fetching associations](fetching-associations) - how to eagerly load related entities 19 | * [Bulk queries](bulk-queries) - how to perform bulk updates/deletes 20 | * [Dapper](dapper) - how to revert to using Dapper 21 | * [Async/sync support](async-support) - async and sync apis 22 | * [Performance](performance) - how does Dashing perform? 23 | -------------------------------------------------------------------------------- /Dashing/Extensions/ReferenceEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Extensions { 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Runtime.CompilerServices; 5 | 6 | /// 7 | /// A generic object comparerer that would only use object's reference, taken from Castle Core. 8 | /// 9 | public class ReferenceEqualityComparer : IEqualityComparer, IEqualityComparer { 10 | private static readonly ReferenceEqualityComparer instance = new ReferenceEqualityComparer(); 11 | 12 | private ReferenceEqualityComparer() { } 13 | 14 | public int GetHashCode(object obj) { 15 | return RuntimeHelpers.GetHashCode(obj); 16 | } 17 | 18 | bool IEqualityComparer.Equals(object x, object y) { 19 | return x == y; 20 | } 21 | 22 | bool IEqualityComparer.Equals(T x, T y) { 23 | return (object)x == (object)y; 24 | } 25 | 26 | int IEqualityComparer.GetHashCode(T obj) { 27 | return RuntimeHelpers.GetHashCode(obj); 28 | } 29 | 30 | public static ReferenceEqualityComparer Instance => instance; 31 | } 32 | } -------------------------------------------------------------------------------- /Dashing/Engine/InMemory/InMemoryDbConnection.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.InMemory { 2 | using System; 3 | using System.Data; 4 | using System.Data.Common; 5 | 6 | internal class InMemoryDbConnection : DbConnection { 7 | private ConnectionState state; 8 | 9 | protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) { 10 | return new InMemoryDbTransaction(this, isolationLevel); 11 | } 12 | 13 | public override void Close() { 14 | this.state = ConnectionState.Closed; 15 | } 16 | 17 | public override void ChangeDatabase(string databaseName) { 18 | 19 | } 20 | 21 | public override void Open() { 22 | this.state = ConnectionState.Open; 23 | } 24 | 25 | public override string ConnectionString { get; set; } 26 | 27 | public override string Database { get; } 28 | 29 | public override ConnectionState State => this.state; 30 | 31 | public override string DataSource { get; } 32 | 33 | public override string ServerVersion { get; } 34 | 35 | protected override DbCommand CreateDbCommand() { 36 | throw new NotImplementedException(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Dashing.Cli/Seeder.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Cli { 2 | using System; 3 | 4 | using Dashing.Configuration; 5 | using Dashing.Engine.Dialects; 6 | 7 | using Serilog; 8 | 9 | public class Seeder { 10 | public void Execute(ISeeder seeder, IConfiguration configuration, string connectionString, string providerName) { 11 | // set up the database connection 12 | var dialectFactory = new DialectFactory(); 13 | var dialect = dialectFactory.Create(providerName, connectionString); 14 | var dbProviderFactoryFactory = new DbProviderFactoryFactory(); 15 | var dbProviderFactory = dbProviderFactoryFactory.Create(providerName, connectionString); 16 | if (!dbProviderFactory.DatabaseExists(connectionString, providerName, dialect)) { 17 | Log.Logger.Error("Database doesn't exist"); 18 | return; 19 | } 20 | 21 | // run the script 22 | var sqlSessionCreator = new SqlDatabase(configuration, dbProviderFactory, connectionString, dialect); 23 | using (var session = sqlSessionCreator.BeginSession()) { 24 | seeder.Seed(session); 25 | session.Complete(); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Dashing.Tests/Engine/DML/FetchTreeParserTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.DML { 2 | using System.Linq; 3 | 4 | using Dashing.Engine.DML; 5 | using Dashing.Tests.TestDomain; 6 | 7 | using Moq; 8 | 9 | using Xunit; 10 | 11 | public class FetchTreeParserTests { 12 | [Fact] 13 | public void FetchReturnsFetchNode() { 14 | var config = new TestConfig(); 15 | var parser = new FetchTreeParser(config); 16 | var query = GetSelectQuery() 17 | .Fetch(p => p.Blog) as SelectQuery; 18 | var queryTree = parser.GetFetchTree(query, out var _, out var _); 19 | Assert.NotNull(queryTree); 20 | Assert.Single(queryTree.Children); 21 | Assert.Equal(nameof(Post.Blog), queryTree.Children.Keys.First()); 22 | Assert.Same(config.GetMap().Columns[nameof(Post.Blog)], queryTree.Children.Values.First().Column); 23 | Assert.True(queryTree.Children.Values.First().IsFetched); 24 | } 25 | 26 | private SelectQuery GetSelectQuery() 27 | where T : class, new() 28 | { 29 | return new SelectQuery(new Mock().Object); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Dashing.CommandLine/LogConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CommandLine { 2 | using System; 3 | using System.Linq; 4 | 5 | using McMaster.Extensions.CommandLineUtils; 6 | 7 | using Serilog; 8 | using Serilog.Events; 9 | 10 | public static class LogConfiguration { 11 | public static void AddLogLevelOption(this CommandLineApplication app) { 12 | app.Option("-l|--log ", "The logging level, one of verbose,debug,information,warning,error,fatal. Defaults to warning", CommandOptionType.SingleValue, true); 13 | } 14 | 15 | public static void EnableLogging(this CommandLineApplication app) { 16 | var logLevel = app.GetOptions().SingleOrDefault(o => o.LongName == "log"); 17 | if (logLevel == null) { 18 | throw new InvalidOperationException(); 19 | } 20 | 21 | if (!logLevel.HasValue() || !Enum.TryParse(logLevel.Value(), true, out LogEventLevel logEventLevel)) { 22 | logEventLevel = LogEventLevel.Warning; 23 | } 24 | 25 | Log.Logger = new LoggerConfiguration().MinimumLevel.Is(logEventLevel) 26 | .WriteTo.Console() 27 | .CreateLogger(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Dashing/Logging/ILog.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Logging 2 | { 3 | using System; 4 | 5 | /// 6 | /// Simple interface that represent a logger. 7 | /// 8 | #if LIBLOG_PUBLIC 9 | public 10 | #else 11 | internal 12 | #endif 13 | interface ILog 14 | { 15 | /// 16 | /// Log a message the specified log level. 17 | /// 18 | /// The log level. 19 | /// The message function. 20 | /// An optional exception. 21 | /// Optional format parameters for the message generated by the messagefunc. 22 | /// true if the message was logged. Otherwise false. 23 | /// 24 | /// Note to implementers: the message func should not be called if the loglevel is not enabled 25 | /// so as not to incur performance penalties. 26 | /// To check IsEnabled call Log with only LogLevel and check the return value, no event will be written. 27 | /// 28 | bool Log(LogLevel logLevel, Func messageFunc, Exception exception = null, 29 | params object[] formatParameters); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docs/testing.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | When you're unit testing you'd generally like to avoid making actual database calls (for various reasons). 4 | 5 | To that end we provide a simple way of mocking out all the SQL stuff in Dashing and replacing it with an in-memory version 6 | of the database. 7 | 8 | ## What do you have to do? 9 | 10 | Instead of using the `SqlDatabase` you can use the `InMemoryDatabase`. As long as all your code depends on ISession or IDatabase you can simply 11 | swap out these implementations during your tests. The majority of the Dashing api will work as expected when being used with in the InMemoryDatabase 12 | (transaction support is a notable omission) and using the `Dapper` property to execute SQL isn't going to work either. 13 | 14 | > For example, you don't have to perform null-checking when run InMemory as the null checks are added for you. In the following code we don't need to check 15 | that Author is not null in sql as the where clause is performed against the Users table (and the nulls propagate as expected). In order for that to work in memory 16 | we re-write the lambda expression with null checks added. 17 | await session.Where(p => p.Author.IsApproved).ToArrayAsync() 18 | 19 | !!! WARNING !!! 20 | 21 | The implementation of InMemoryEngine, while not bad, may not exactly match what your database. -------------------------------------------------------------------------------- /Dashing.Tests/Extensions/DynamicParametersExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Extensions { 2 | using System; 3 | using System.Reflection; 4 | 5 | using Dapper; 6 | 7 | public static class DynamicParametersExtensions { 8 | // TODO: Put this in an extension method 9 | public static object GetValueOfParameter(this DynamicParameters p, string parameterName) { 10 | var parametersField = typeof(DynamicParameters).GetField("parameters", BindingFlags.NonPublic | BindingFlags.Instance); 11 | if (parametersField == null) { 12 | throw new Exception("Could not reflect the parameters field of the DynamicParameters object"); 13 | } 14 | 15 | dynamic parameters = parametersField.GetValue(p); 16 | 17 | foreach (var paramInfoPair in parameters) { 18 | var paramInfo = paramInfoPair.GetType().GetProperty("Value").GetValue(paramInfoPair); 19 | var paramName = paramInfo.GetType().GetProperty("Name").GetValue(paramInfo); 20 | var paramValue = paramInfo.GetType().GetProperty("Value").GetValue(paramInfo); 21 | 22 | if (paramName == parameterName) { 23 | return paramValue; 24 | } 25 | } 26 | 27 | return null; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Dashing/Extensions/DapperExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Extensions { 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | 7 | using Dapper; 8 | 9 | public static class DapperExtensions { 10 | public static object GetValue(this DynamicParameters parameters, string key) { 11 | var parametersProperty = typeof(DynamicParameters).GetField("parameters", BindingFlags.NonPublic | BindingFlags.Instance); 12 | var explicitParameters = parametersProperty.GetValue(parameters); 13 | 14 | if (explicitParameters != null) { 15 | foreach (var explicitParameter in (IDictionary)explicitParameters) { 16 | string paramKey = (string)explicitParameter.GetType().GetProperty("Key").GetValue(explicitParameter, null); 17 | var valueProperty = explicitParameter.GetType().GetProperty("Value").GetValue(explicitParameter, null); 18 | if (paramKey == key) { 19 | return valueProperty.GetType().GetProperty("Value").GetValue(valueProperty, null); 20 | } 21 | } 22 | } 23 | 24 | throw new ArgumentException("No such key in the parameters dictionary"); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Dashing/SessionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Threading.Tasks; 3 | 4 | public static class SessionExtensions { 5 | public static int Insert(this ISession session, params T[] entities) 6 | where T : class, new() { 7 | return session.Insert(entities); 8 | } 9 | 10 | public static int Save(this ISession session, params T[] entities) 11 | where T : class, new() { 12 | return session.Save(entities); 13 | } 14 | 15 | public static int Delete(this ISession session, params T[] entities) 16 | where T : class, new() { 17 | return session.Delete(entities); 18 | } 19 | 20 | public static Task InsertAsync(this ISession session, params T[] entities) 21 | where T : class, new() { 22 | return session.InsertAsync(entities); 23 | } 24 | 25 | public static Task SaveAsync(this ISession session, params T[] entities) 26 | where T : class, new() { 27 | return session.SaveAsync(entities); 28 | } 29 | 30 | public static Task DeleteAsync(this ISession session, params T[] entities) 31 | where T : class, new() { 32 | return session.DeleteAsync(entities); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Tests/DapperWrapperTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Tests { 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | 5 | using Dashing.IntegrationTests.Setup; 6 | 7 | using Xunit; 8 | 9 | public class DapperWrapperTests { 10 | [Theory] 11 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 12 | public async Task DynamicQueryAsyncWorks(TestSessionWrapper wrapper) { 13 | var result = await wrapper.Session.Dapper.QueryAsync("select 1 as Id"); 14 | Assert.Single(result); 15 | Assert.Equal(1, result.First().Id); 16 | } 17 | 18 | [Theory] 19 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 20 | public async Task StronglyTypedQueryWorks(TestSessionWrapper wrapper) { 21 | var result = await wrapper.Session.Dapper.QueryAsync("select 1 as FooId, 'Rah' as Bar"); 22 | Assert.Single(result); 23 | Assert.Equal(1, result.First().FooId); 24 | Assert.Equal("Rah", result.First().Bar); 25 | } 26 | 27 | public class Foo { 28 | public int FooId { get; set; } 29 | 30 | public string Bar { get; set; } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /docs/configuration-indexes.md: -------------------------------------------------------------------------------- 1 | --- 2 | configuration: true 3 | --- 4 | 5 | # Indexes 6 | 7 | Adding indexes to your database schema is done using the configuration object. These 8 | indexes can then be created using the dash tool. 9 | 10 | By default indexes are automatically created on all properties that are many-to-one or one-to-one relations. 11 | This is done on the premise that you will be using these relationships in fetch queries (joins) and that 12 | these will benefit from the indexes. 13 | 14 | To specifically add a new index use the Index() method on a particular IMap instance. 15 | For example, if you'd like to index the Title property on your Blog class you would set 16 | up your configuration like so: 17 | 18 | public class DashingConfiguration : DefaultConfiguration { 19 | public DashingConfiguration() { 20 | // add the domain classes to the config 21 | this.AddNamespaceOf(); 22 | 23 | // add any extra indexes 24 | this.Setup().Index(b => new { b.Title }, false); 25 | } 26 | } 27 | 28 | Notice that the second argument to the function indicates whether you would like the index to be unique or not. 29 | 30 | Note: By default any indexes that contain nullable columns will generate a 31 | [filtered index](http://msdn.microsoft.com/en-gb/library/cc280372.aspx) in sql server. -------------------------------------------------------------------------------- /Dashing/ReverseEngineering/Column.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ReverseEngineering { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Dashing.SchemaReading; 6 | 7 | internal class Column : Dashing.Configuration.Column, IReverseEngineeringColumn { 8 | private readonly object typeLock = new object(); 9 | 10 | private Type actualType; 11 | 12 | public override Type Type 13 | { 14 | get 15 | { 16 | if (this.actualType == null) { 17 | lock (this.typeLock) { 18 | if (this.actualType == null) { 19 | if (string.IsNullOrEmpty(this.ForeignKeyTableName)) { 20 | this.actualType = base.Type; 21 | } 22 | else { 23 | this.actualType = this.TypeMap[this.ForeignKeyTableName]; 24 | } 25 | } 26 | } 27 | } 28 | 29 | return this.actualType; 30 | } 31 | } 32 | 33 | public string ForeignKeyTableName { get; set; } 34 | 35 | public IDictionary TypeMap { get; set; } 36 | 37 | public ColumnDto ColumnSpecification { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /Dashing/Logging/LogProviders/TraceEventTypeValues.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Logging.LogProviders 2 | { 3 | using System; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | using Dashing.Extensions; 7 | 8 | #if LIBLOG_EXCLUDE_CODE_COVERAGE 9 | [ExcludeFromCodeCoverage] 10 | #endif 11 | internal static class TraceEventTypeValues 12 | { 13 | internal static readonly Type Type; 14 | internal static readonly int Verbose; 15 | internal static readonly int Information; 16 | internal static readonly int Warning; 17 | internal static readonly int Error; 18 | internal static readonly int Critical; 19 | 20 | [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")] 21 | static TraceEventTypeValues() 22 | { 23 | var assembly = typeof(Uri).Assembly(); 24 | Type = assembly.GetType("System.Diagnostics.TraceEventType"); 25 | if (Type == null) return; 26 | Verbose = (int) Enum.Parse(Type, "Verbose", false); 27 | Information = (int) Enum.Parse(Type, "Information", false); 28 | Warning = (int) Enum.Parse(Type, "Warning", false); 29 | Error = (int) Enum.Parse(Type, "Error", false); 30 | Critical = (int) Enum.Parse(Type, "Critical", false); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NuGet/Init.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | Write-Host "Installing Dashing" 4 | Write-Host "Install Path: " -nonewline; Write-Host $installPath 5 | Write-Host "Tools Path: " -nonewline; Write-Host $toolsPath 6 | Write-Host "Package: " -nonewline; Write-Host $package 7 | Write-Host "Project: " -nonewline; Write-Host $project 8 | 9 | 10 | # find out where to put the files, we're going to create a deploy directory 11 | # at the same level as the solution. 12 | 13 | $rootDir = (Get-Item $installPath).parent.parent.fullname 14 | $deployTarget = "$rootDir\Dashing" 15 | Write-Host "Deploy Target: " -nonewline; Write-Host $deployTarget 16 | 17 | $appConfigFileDir = [IO.Path]::Combine($installPath, 'tools/net46/') 18 | $appConfigFile = [IO.Path]::Combine($installPath, 'tools/net46/dash.exe.config') 19 | $appConfig = New-Object XML 20 | $appConfig.Load($appConfigFile) 21 | $node = $appConfig.SelectSingleNode('configuration/appSettings/add[@key="AssemblySearchPaths"]') 22 | $node.Attributes['value'].Value = $appConfigFileDir 23 | $appConfig.Save($appConfigFile) 24 | 25 | # create our deploy support directory if it doesn't exist yet 26 | if (!(Test-Path $deployTarget)) { 27 | mkdir $deployTarget 28 | } 29 | 30 | Copy-Item $installPath\tools\net46\dash.exe $deployTarget -Recurse -Force 31 | Copy-Item $installPath\tools\net46\dash.exe.config $deployTarget -Recurse -Force 32 | -------------------------------------------------------------------------------- /Dashing/Engine/InMemory/WhereClauseOpEqualityRewriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.InMemory { 2 | using System; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | 6 | using Dashing.Extensions; 7 | 8 | public class WhereClauseOpEqualityRewriter : ExpressionVisitor { 9 | public Expression> Rewrite(Expression> expression) { 10 | return Expression.Lambda>(this.Visit(expression.Body), expression.Parameters.First()); 11 | } 12 | 13 | protected override Expression VisitBinary(BinaryExpression node) { 14 | if (node.NodeType == ExpressionType.Equal 15 | && !node.Left.Type.IsValueType() // only change entity expressions 16 | && node.Left.Type != typeof(string) // ignore strings as well 17 | && !IsNullConstant(node.Left) // don't re-write null checks 18 | && !IsNullConstant(node.Right) // don't re-write null checks 19 | ) { 20 | return Expression.Call(node.Left, "Equals", new Type[0], node.Right); 21 | } 22 | 23 | return base.VisitBinary(node); 24 | } 25 | 26 | private static bool IsNullConstant(Expression expression) { 27 | return expression.NodeType == ExpressionType.Constant && ((ConstantExpression)expression).Value == null; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Dashing.Tests/NeedToDash.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests { 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | /// 6 | /// Provides methods to configure Dashing in a single statement. 7 | /// 8 | public static class NeedToDash { 9 | /// 10 | /// Returns a Configuration object for the connection string that can be fluently configured 11 | /// 12 | /// connection string settings for the database to be used 13 | /// Mutable configuration object 14 | public static MutableConfiguration Configure() { 15 | return new MutableConfiguration(); 16 | } 17 | 18 | /// 19 | /// Returns a Configuration object for the connection string that can be fluently configured 20 | /// 21 | /// connection string settings for the database to be used 22 | /// Enumerable of types to be mapped 23 | /// Mutable configuration object 24 | public static MutableConfiguration Configure(IEnumerable types) { 25 | var configuration = new MutableConfiguration(); 26 | configuration.Add(types); 27 | return configuration; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Tests/TransactionTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Tests { 2 | public class TransactionTests { 3 | //[Theory] 4 | //[MemberData("GetSessions", MemberType = typeof(SessionDataGenerator))] 5 | //public void TestTransactioning(TestSessionWrapper wrapper) { 6 | // // scrap the current transaction 7 | // wrapper.Session.Complete(); 8 | // wrapper.Session.Dispose(); 9 | 10 | // using (var session = wrapper.Session.Configuration.BeginSession()) { 11 | // session.Insert(new User { Username = "james", EmailAddress = "james@polylytics.com" }); 12 | // session.Complete(); 13 | // } 14 | 15 | // using (var session = wrapper.Session.Configuration.BeginSession()) { 16 | // Assert.NotNull(session.Query().SingleOrDefault(u => u.Username == "james")); 17 | // session.Delete(u => u.Username == "james"); 18 | // Assert.Null(session.Query().SingleOrDefault(u => u.Username == "james")); 19 | // } 20 | 21 | // using (var session = wrapper.Session.Configuration.BeginSession()) { 22 | // Assert.NotNull(session.Query().SingleOrDefault(u => u.Username == "james")); 23 | // } 24 | 25 | // wrapper.Session = wrapper.Session.Configuration.BeginSession(); 26 | //} 27 | } 28 | } -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Tests/EnumeratingTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Tests { 2 | using System; 3 | 4 | using Dashing.IntegrationTests.Setup; 5 | using Dashing.IntegrationTests.TestDomain; 6 | 7 | using Xunit; 8 | 9 | public class EnumeratingTests { 10 | [Theory] 11 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 12 | public void TestSingleAndFirst(TestSessionWrapper wrapper) { 13 | // now fetch them 14 | var t1 = wrapper.Session.Query().First(); 15 | Assert.Equal("User_0", t1.Username); 16 | 17 | var t2 = wrapper.Session.Query().First(u => u.Username == "User_1"); 18 | Assert.Equal("User_1", t2.Username); 19 | 20 | Assert.Throws(() => wrapper.Session.Query().Single()); 21 | 22 | var t3 = wrapper.Session.Query().Single(u => u.Username == "User_2"); 23 | Assert.Equal("User_2", t3.Username); 24 | 25 | var t4 = wrapper.Session.Query().FirstOrDefault(); 26 | Assert.Equal("User_0", t1.Username); 27 | 28 | var t5 = wrapper.Session.Query().FirstOrDefault(u => u.Username == "Boo"); 29 | Assert.Null(t5); 30 | 31 | var t6 = wrapper.Session.Query().SingleOrDefault(u => u.Username == "Boo"); 32 | Assert.Null(t6); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Dashing/ReverseEngineering/DefaultConvention.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.ReverseEngineering { 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Dashing.Extensions; 6 | 7 | public class DefaultConvention : IConvention { 8 | private readonly IDictionary extraWords; 9 | 10 | /// 11 | /// 12 | /// 13 | /// A string containing extra pluralization words 14 | /// in the form Singular1,Plural1|Singular2,Plural2|Singular3,Plural3 ... 15 | /// 16 | public DefaultConvention(IEnumerable> extraPluralizationWords) { 17 | this.extraWords = (extraPluralizationWords ?? new Dictionary()).ToDictionary(k => k.Value.ToLowerInvariant(), k => k.Key); 18 | } 19 | 20 | public string PropertyNameForManyToOneColumnName(string columnName) { 21 | if (columnName.EndsWith("Id")) { 22 | return columnName.Substring(0, columnName.Length - 2); 23 | } 24 | 25 | return columnName; 26 | } 27 | 28 | public string ClassNameFor(string tableName) { 29 | if (this.extraWords.ContainsKey(tableName.ToLowerInvariant())) { 30 | return this.extraWords[tableName.ToLowerInvariant()]; 31 | } 32 | 33 | return tableName.Singularize(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Dashing/InMemoryDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System.Data; 3 | 4 | using Dashing.Configuration; 5 | using Dashing.Engine; 6 | using Dashing.Engine.InMemory; 7 | 8 | public class InMemoryDatabase : IDatabase { 9 | protected readonly IConfiguration configuration; 10 | 11 | protected InMemoryEngine engine; 12 | 13 | public bool CompleteFailsSilentlyIfRejected { get; set; } 14 | 15 | public InMemoryDatabase(IConfiguration configuration) { 16 | this.configuration = configuration; 17 | this.engine = new InMemoryEngine(configuration); 18 | } 19 | 20 | public virtual ISession BeginSession(IDbConnection connection = null, IDbTransaction transaction = null) { 21 | return new Session(this.engine, 22 | new System.Lazy(() => new InMemoryDbConnection()), 23 | null, 24 | false, 25 | false, 26 | true, 27 | this.CompleteFailsSilentlyIfRejected); 28 | } 29 | 30 | public virtual ISession BeginTransactionLessSession(IDbConnection connection = null) { 31 | return new Session(this.engine, 32 | new System.Lazy(() => new InMemoryDbConnection()), 33 | null, 34 | false, 35 | false, 36 | true, 37 | this.CompleteFailsSilentlyIfRejected); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Dashing/Logging/ILogProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Dashing.Logging 6 | { 7 | /// 8 | /// Represents a way to get a 9 | /// 10 | #if LIBLOG_PROVIDERS_ONLY 11 | internal 12 | #else 13 | public 14 | #endif 15 | interface ILogProvider 16 | { 17 | /// 18 | /// Gets the specified named logger. 19 | /// 20 | /// Name of the logger. 21 | /// The logger reference. 22 | Logger GetLogger(string name); 23 | 24 | /// 25 | /// Opens a nested diagnostics context. Not supported in EntLib logging. 26 | /// 27 | /// The message to add to the diagnostics context. 28 | /// A disposable that when disposed removes the message from the context. 29 | IDisposable OpenNestedContext(string message); 30 | 31 | /// 32 | /// Opens a mapped diagnostics context. Not supported in EntLib logging. 33 | /// 34 | /// A key. 35 | /// A value. 36 | /// A disposable that when disposed removes the map from the context. 37 | IDisposable OpenMappedContext(string key, object value, bool destructure = false); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Dashing.PerformanceTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net46;net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | $(MSBuildThisFileDirectory)../Dashing.Weaver/bin/$(Configuration)/net46/dashing-weaver.exe 28 | dotnet "$(MSBuildThisFileDirectory)../Dashing.Weaver/bin/$(Configuration)/net9.0/dashing-weaver.dll" 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Setup/TestDatabaseGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Setup { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | using Dashing.Configuration; 9 | using Dashing.Extensions; 10 | 11 | public class TestDatabaseGenerator { 12 | private static readonly IList TestSessions = new List(); 13 | 14 | static TestDatabaseGenerator() { 15 | // delete the sqlite db if exists 16 | if (File.Exists("testdb.db")) { 17 | File.Delete("testdb.db"); 18 | } 19 | 20 | // generate all the sessions 21 | var sessionCreatorTypes = typeof(TestDatabaseGenerator).Assembly().GetTypes().Where(t => t.Namespace == "Dashing.IntegrationTests.Setup" && typeof(IDatabase).IsAssignableFrom(t) && t.IsPublic()).ToArray(); 22 | var config = new Configuration(); 23 | foreach (var sessionCreatorType in sessionCreatorTypes) { 24 | var sessionCreator = (SqlDatabase)Activator.CreateInstance(sessionCreatorType, config); 25 | var dbInitializer = new DatabaseInitializer(sessionCreator, config); 26 | TestSessions.Add(dbInitializer.Initialize()); 27 | } 28 | } 29 | 30 | public static IEnumerable SessionWrappers { 31 | get { 32 | return TestSessions; 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Dashing/Extensions/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Extensions { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | public static class EnumerableExtensions { 7 | public static bool IsEmpty(this IEnumerable source) { 8 | return !source.Any(); 9 | } 10 | 11 | public static IEnumerable> Subsets(this IEnumerable source) { 12 | var list = source.ToList(); 13 | int length = list.Count; 14 | var max = (int)Math.Pow(2, list.Count); 15 | 16 | for (int count = 0; count < max; count++) { 17 | var subset = new List(); 18 | uint rs = 0; 19 | while (rs < length) { 20 | if ((count & (1u << (int)rs)) > 0) { 21 | subset.Add(list[(int)rs]); 22 | } 23 | 24 | rs++; 25 | } 26 | 27 | yield return subset; 28 | } 29 | } 30 | 31 | /// 32 | /// Get index details about IEnumerable as you iterate 33 | /// 34 | /// Type of enumerable 35 | /// Source enumerable 36 | /// A new SmartEnumerable of the appropriate type 37 | public static SmartEnumerable AsSmartEnumerable(this IEnumerable source) { 38 | return new SmartEnumerable(source); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Dashing/FetchMany.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | public class FetchMany : IFetchMany 7 | where TOriginal : class, new() { 8 | private readonly SelectQuery query; 9 | 10 | private KeyValuePair> fetchExpression; 11 | 12 | public FetchMany(Expression>> selector, SelectQuery query) { 13 | this.query = query; 14 | this.fetchExpression = new KeyValuePair>(selector, new List()); 15 | this.query.CollectionFetches.Add(this.fetchExpression); 16 | } 17 | 18 | public FetchMany(KeyValuePair> currentFetchExpression, SelectQuery query) { 19 | this.fetchExpression = currentFetchExpression; 20 | this.query = query; 21 | } 22 | 23 | public ISelectQuery ThenFetch(Expression> selector) { 24 | this.fetchExpression.Value.Add(selector); 25 | return this.query; 26 | } 27 | 28 | public IFetchMany ThenFetchMany(Expression>> selector) { 29 | this.fetchExpression.Value.Add(selector); 30 | return new FetchMany(this.fetchExpression, this.query); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /docs/async-support.md: -------------------------------------------------------------------------------- 1 | --- 2 | queries: true 3 | --- 4 | 5 | # Async/sync support 6 | 7 | We've designed Dashing so that all statements which hit the database (or could) make use 8 | of the async-await support from C# 5.0. 9 | 10 | However, if you need to keep your code synchronous then every method has a synchronous 11 | partner which is usually the same method signature but without the Async in the name e.g. 12 | 13 | * GetAsync -> Get 14 | * InsertAsync -> Insert 15 | * SaveAsync -> Save 16 | * DeleteAsync -> Delete 17 | 18 | Dashing also supports the use of MARS ([Multiple Active Result Sets](https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/multiple-active-result-sets-mars)) so that you can execute 19 | multiple queries concurrently and then await the results as you need them e.g. 20 | 21 | var commentsTask = session.Query().Where(c => c.Post.PostId == 1).ToListAsync(); // sends query to the database, immediately continues here 22 | var relatedPostsTask = session.Query().Fetch(rp => rp.RelatedPost).Where(rp => rp.Post.PostId == 1).ToListAsync(); // as above 23 | 24 | ... // some other code 25 | 26 | var comments = await commentsTask; // waits for the comments database query to return 27 | 28 | ... // do some stuff with comments 29 | 30 | var relatedPosts = await relatedPostsTask; // waits for the related posts query to return 31 | 32 | Using the above you can easily queue all queries concurrently and then use the results when you need them. 33 | In an ASP.NET application this should minimise the time taken to execute the whole page. -------------------------------------------------------------------------------- /Dashing/Extensions/AsyncLock.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Extensions { 2 | using System; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | /// 7 | /// see http://www.hanselman.com/blog/ComparingTwoTechniquesInNETAsynchronousCoordinationPrimitives.aspx 8 | /// 9 | public sealed class AsyncLock { 10 | private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); 11 | 12 | private readonly Task m_releaser; 13 | 14 | public AsyncLock() { 15 | this.m_releaser = Task.FromResult((IDisposable)new Releaser(this)); 16 | } 17 | 18 | public Task LockAsync() { 19 | var wait = this.m_semaphore.WaitAsync(); 20 | return wait.IsCompleted 21 | ? this.m_releaser 22 | : wait.ContinueWith( 23 | (_, state) => (IDisposable)state, 24 | this.m_releaser.Result, 25 | CancellationToken.None, 26 | TaskContinuationOptions.ExecuteSynchronously, 27 | TaskScheduler.Default); 28 | } 29 | 30 | private sealed class Releaser : IDisposable { 31 | private readonly AsyncLock m_toRelease; 32 | 33 | internal Releaser(AsyncLock toRelease) { 34 | this.m_toRelease = toRelease; 35 | } 36 | 37 | public void Dispose() { 38 | this.m_toRelease.m_semaphore.Release(); 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /NuGet/dashing-weaver.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dashing.Weaver 5 | $version$ 6 | Dashing Weaver 7 | Polylytics 8 | Polylytics 9 | https://github.com/Polylytics/dashing 10 | http://polylytics.com/dashing/dashing-icon.png 11 | false 12 | Dashing.Weaver is a compile time tool for adding behaviour to a Dashing domain model 13 | © Polylytics Limited, 2018 14 | en-GB 15 | dashing dapper orm sql mini-orm 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Dashing.Tests/Configuration/ColumnTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Configuration { 2 | using System; 3 | using System.Linq; 4 | using System.Reflection; 5 | #if COREFX 6 | using System.Reflection; 7 | #endif 8 | 9 | using Dashing.Configuration; 10 | using Dashing.Tests.Extensions; 11 | using Dashing.Tests.TestDomain; 12 | 13 | using Xunit; 14 | 15 | public class ColumnTests { 16 | [Fact] 17 | public void FromThrowsIfColumnIsNull() { 18 | Assert.Throws(() => Column.From(null)); 19 | } 20 | 21 | [Fact] 22 | public void FromThrowsIfColumnIsIncorrectType() { 23 | Assert.Throws(() => Column.From(new Column())); 24 | } 25 | 26 | [Fact] 27 | public void FromPopulatesAllProperties() { 28 | // assemble a populated column 29 | var column = new Column().Populate() as IColumn; 30 | 31 | // act 32 | var genericColumn = Column.From(column); 33 | 34 | // assert all properties are equal 35 | var columnType = column.GetType(); 36 | var genericColumnType = genericColumn.GetType(); 37 | foreach (var prop in columnType.GetProperties().Where(p => p.Name != "ChildColumn" && p.Name != "ParentMap" && p.Name != "OppositeColumn" && p.Name != "Default") 38 | ) { 39 | Assert.Equal(prop.GetValue(column, null), genericColumnType.GetProperty(prop.Name).GetValue(genericColumn, null)); 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Dashing.Weaving.Tests/ForeignKeyTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Weaving.Tests { 2 | using System; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | using Dashing.Weaving.Sample.Domain; 7 | 8 | using Xunit; 9 | 10 | [Collection("Weaving Tests")] 11 | public class ForeignKeyTests { 12 | [Fact] 13 | public void NullReturnsNull() { 14 | var bar = new Bar(); 15 | Assert.Null(bar.Foo); 16 | } 17 | 18 | [Fact] 19 | public void FkFieldExists() { 20 | Assert.True(typeof(Bar).GetFields().SingleOrDefault(f => f.Name == "FooId") != null); 21 | } 22 | 23 | [Fact] 24 | public void FkFieldHasCorrectType() { 25 | Assert.Equal(typeof(Nullable<>).MakeGenericType(typeof(int)), typeof(Bar).GetFields().Single(f => f.Name == "FooId").FieldType); 26 | } 27 | 28 | [Fact] 29 | public void ReturnFooWithId() { 30 | var bar = new Bar(); 31 | typeof(Bar).GetField("FooId").SetValue(bar, 3); 32 | Assert.Equal(3, bar.Foo.FooId); 33 | } 34 | 35 | [Fact] 36 | public void ChangeFooChanges() { 37 | var bar = new Bar(); 38 | typeof(Bar).GetField("FooId").SetValue(bar, 3); 39 | bar.Foo = new Foo { FooId = 4 }; 40 | Assert.Equal(4, bar.Foo.FooId); 41 | } 42 | 43 | [Fact] 44 | public void ChangeToNullResets() { 45 | var bar = new Bar(); 46 | typeof(Bar).GetField("FooId").SetValue(bar, 3); 47 | bar.Foo = null; 48 | Assert.Null(bar.Foo); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /docs/configuration-conventions.md: -------------------------------------------------------------------------------- 1 | --- 2 | configuration: true 3 | --- 4 | 5 | # Conventions 6 | 7 | The BaseConfiguration class, if you're extending it, allows you to specify an 8 | IConvention for mapping classes to tables. 9 | 10 | string TableFor(Type entity); 11 | string SchemaFor(Type entity); 12 | string PrimaryKeyFor(Type entity, IEnumerable propertyNames); 13 | bool IsPrimaryKeyAutoGenerated(IColumn primaryKeyColumn); 14 | ushort StringLengthFor(Type entity, string propertyName); 15 | byte DecimalPrecisionFor(Type entity, string propertyName); 16 | byte DecimalScaleFor(Type entity, string propertyName); 17 | 18 | The default convention, "DefaultConvention"(!), does the following: 19 | 20 | TableFor 21 | ----------- 22 | 23 | Uses the PluralizationService from System.Data.Entity.Design.PluralizationServices (with an en-GB culture) to 24 | pluralize class names. 25 | 26 | SchemaFor 27 | ------------ 28 | 29 | null (!!) 30 | 31 | PrimaryKeyFor 32 | ------------- 33 | 34 | Selects the primary key by convention from the properties. Either FooId (where Foo is the class name), Id or ID by default. 35 | 36 | IsPrimaryKeyAutoGenerated 37 | ---------------- 38 | 39 | If it's an int, long or guid then yes, otherwise no. If set to true for a particular table it's assumed the primary key 40 | is generated on insert, in which case the primary key is fetched after insert and set on the entity. 41 | 42 | StringLengthFor 43 | ---------------- 44 | 45 | 255 46 | 47 | DecimalPrecisionFor 48 | ---------------- 49 | 50 | 18 51 | 52 | DecimalScaleFor 53 | ---------------- 54 | 55 | 10 56 | 57 | The last 3 can be provided via the DefaultConvention constructor. 58 | -------------------------------------------------------------------------------- /Dashing.PerformanceTests/Tests/EntityFramework/EfContext.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.PerformanceTests.Tests.EntityFramework { 2 | #if NET46 3 | using System.Data.Entity; 4 | 5 | using global::Dashing.PerformanceTests.Domain; 6 | 7 | using PerformanceTest; 8 | 9 | internal class EfContext : DbContext { 10 | public EfContext() 11 | : base(Program.ConnectionString) { } 12 | 13 | protected override void OnModelCreating(DbModelBuilder modelBuilder) { 14 | // @formatter:off 15 | modelBuilder.Entity().HasOptional(p => p.Author).WithMany().Map(e => e.MapKey("AuthorId")); 16 | modelBuilder.Entity().HasOptional(p => p.Blog).WithMany(b => b.Posts).Map(e => e.MapKey("BlogId")); 17 | modelBuilder.Entity().HasOptional(c => c.Post).WithMany().Map(e => e.MapKey("PostId")); 18 | modelBuilder.Entity().HasOptional(c => c.User).WithMany().Map(e => e.MapKey("UserId")); 19 | modelBuilder.Entity().HasMany(p => p.Comments).WithOptional(c => c.Post); 20 | modelBuilder.Entity().HasMany(p => p.Tags).WithOptional(p => p.Post); 21 | modelBuilder.Entity().HasOptional(c => c.Post).WithMany().Map(e => e.MapKey("PostId")); 22 | modelBuilder.Entity().HasOptional(c => c.Tag).WithMany().Map(e => e.MapKey("TagId")); 23 | // @formatter:on 24 | } 25 | 26 | public DbSet Posts { get; set; } 27 | 28 | public DbSet Users { get; set; } 29 | 30 | public DbSet Blogs { get; set; } 31 | 32 | public DbSet Comments { get; set; } 33 | } 34 | 35 | #endif 36 | 37 | } -------------------------------------------------------------------------------- /Dashing/CodeGeneration/TrackingCollection.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CodeGeneration { 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Collections.Specialized; 5 | 6 | public sealed class TrackingCollection : ObservableCollection 7 | where TEntity : ITrackedEntity { 8 | private readonly TEntity entity; 9 | 10 | private readonly string propertyName; 11 | 12 | public TrackingCollection(TEntity entity, string propertyName) 13 | : this(entity, propertyName, new List()) { 14 | //// This is deliberately empty 15 | } 16 | 17 | public TrackingCollection(TEntity entity, string propertyName, IEnumerable collection) 18 | : base(collection) { 19 | this.entity = entity; 20 | this.propertyName = propertyName; 21 | this.CollectionChanged += this.TrackingCollection_CollectionChanged; 22 | } 23 | 24 | private void TrackingCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { 25 | if (this.entity.IsTrackingEnabled()) { 26 | if (e.OldItems != null) { 27 | foreach (var entity in e.OldItems) { 28 | //this.entity.DeletedEntities[this.propertyName].Add(entity); 29 | } 30 | } 31 | 32 | if (e.NewItems != null) { 33 | foreach (var entity in e.NewItems) { 34 | //this.entity.AddedEntities[this.propertyName].Add(entity); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Dashing.Cli/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Cli { 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Dashing.Cli.Commands; 6 | using Dashing.CommandLine; 7 | 8 | using McMaster.Extensions.CommandLineUtils; 9 | 10 | #if !COREFX 11 | using System.Configuration; 12 | #endif 13 | 14 | public class Program { 15 | #if COREFX 16 | internal static readonly IList AssemblySearchDirectories = new List(); 17 | #else 18 | internal static readonly IList AssemblySearchDirectories = (ConfigurationManager.AppSettings["AssemblySearchPaths"] 19 | ?.Split(';') ?? Enumerable.Empty()).ToList(); 20 | #endif 21 | 22 | public static int Main(string[] args) { 23 | AssemblyResolution.Configure(AssemblySearchDirectories); // we have to configure the assembly resolution on it's own in this method as the ExecuteApplication needs it 24 | return ExecuteApplication(args); 25 | } 26 | 27 | private static int ExecuteApplication(string[] args) { 28 | var app = new CommandLineApplication { 29 | Name = "dash", 30 | Description = "Provides functionality to migrate databases" 31 | }; 32 | app.AddLogLevelOption(); 33 | app.HelpOption(inherited: true); 34 | app.UseScript(); 35 | app.UseMigrate(); 36 | app.UseSeed(); 37 | app.UseAddWeave(); 38 | return app.Execute(args); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Dashing.CommandLine/AssemblyContext.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.CommandLine { 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | using Dashing.Extensions; 8 | 9 | #if COREFX 10 | using System.Runtime.Loader; 11 | #endif 12 | 13 | public static class AssemblyContext { 14 | public static Assembly LoadFile(string assemblyPath) { 15 | #if COREFX 16 | return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath); 17 | #else 18 | return Assembly.LoadFile(assemblyPath); 19 | #endif 20 | } 21 | 22 | public static TInterfaceType LoadType(string assemblyPath, string configurationFullName) 23 | where TInterfaceType : class { 24 | if (!File.Exists(assemblyPath)) { 25 | throw new Exception($"Unable to find assembly at {assemblyPath}"); 26 | } 27 | 28 | if (!Path.IsPathRooted(assemblyPath)) { 29 | assemblyPath = Path.GetFullPath(assemblyPath); 30 | } 31 | 32 | var assembly = LoadFile(assemblyPath); 33 | var type = assembly.GetLoadableTypes() 34 | .SingleOrDefault(t => t.FullName == configurationFullName); 35 | if (type == null) { 36 | throw new Exception($"Unable to find configuration of type {configurationFullName} in {assemblyPath}"); 37 | } 38 | 39 | if (!(Activator.CreateInstance(type) is TInterfaceType instance)) { 40 | throw new Exception($"The type {configurationFullName} does not implement IConfiguration"); 41 | } 42 | 43 | return instance; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/MemberExpressionFetchNodeVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System; 3 | using System.Linq.Expressions; 4 | 5 | abstract class MemberExpressionFetchNodeVisitor { 6 | protected BaseQueryNode VisitExpression(Expression expr, QueryTree rootQueryNode) { 7 | var memberExpr = expr as MemberExpression; 8 | if (memberExpr == null) { 9 | throw new InvalidOperationException("Order/Include/Exclude clauses must contain MemberExpressions"); 10 | } 11 | 12 | if (memberExpr.Expression.NodeType == ExpressionType.Parameter) { 13 | // we're at the bottom 14 | return rootQueryNode; // this should be the root queryNode 15 | } 16 | 17 | // not at the bottom, find the child and return that 18 | var parentNode = this.VisitExpression(memberExpr.Expression, rootQueryNode); 19 | if (parentNode == null) { 20 | throw new InvalidOperationException("You must Fetch a relationship if you want to use it in an order by or include/exclude clause"); 21 | } 22 | 23 | var baseExpr = memberExpr.Expression as MemberExpression; 24 | if (baseExpr == null) { 25 | throw new InvalidOperationException("Order/Include/Exclude clauses must contain MemberExpressions"); 26 | } 27 | 28 | if (!parentNode.Children.ContainsKey(baseExpr.Member.Name)) { 29 | throw new InvalidOperationException($"You must Fetch {baseExpr.Member.Name} if you wish to you it in an Order/Include/Exclude clause"); 30 | } 31 | 32 | return parentNode.Children[baseExpr.Member.Name]; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Dashing.PerformanceTests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Dashing.IntegrationTests/Tests/AsyncTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.IntegrationTests.Tests { 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | 5 | using Dashing.IntegrationTests.Setup; 6 | using Dashing.IntegrationTests.TestDomain; 7 | 8 | using Xunit; 9 | 10 | public class AsyncTests { 11 | [Theory] 12 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 13 | public async Task GetByIdWorks(TestSessionWrapper wrapper) { 14 | var post = await wrapper.Session.GetAsync(1); 15 | Assert.Equal(1, post.PostId); 16 | } 17 | 18 | [Theory] 19 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 20 | public async Task QueryWorks(TestSessionWrapper wrapper) { 21 | var posts = await wrapper.Session.Query().ToListAsync(); 22 | Assert.Equal(20, posts.Count()); 23 | } 24 | 25 | [Theory] 26 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 27 | public async Task CollectionWorks(TestSessionWrapper wrapper) { 28 | var posts = await wrapper.Session.Query().Fetch(p => p.Comments).ToListAsync(); 29 | Assert.Equal(20, posts.Count()); 30 | } 31 | 32 | [Theory] 33 | [MemberData(nameof(SessionDataGenerator.GetSessions), MemberType = typeof(SessionDataGenerator))] 34 | public async Task InsertWorks(TestSessionWrapper wrapper) { 35 | var comment = new Comment { Content = "Foo" }; 36 | await wrapper.Session.InsertAsync(comment); 37 | Assert.NotEqual(0, comment.CommentId); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Dashing.Tests/Dashing.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net46;net9.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | $(MSBuildThisFileDirectory)../Dashing.Weaver/bin/$(Configuration)/net46/dashing-weaver.exe 25 | dotnet "$(MSBuildThisFileDirectory)../Dashing.Weaver/bin/$(Configuration)/net9.0/dashing-weaver.dll" 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Dashing.Tests/Engine/DML/WhereClauseWriterPerformanceTests.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Tests.Engine.DML { 2 | using Dashing.Configuration; 3 | using Dashing.Tests.TestDomain; 4 | 5 | public class WhereClauseWriterPerformanceTests { 6 | //[Fact(Skip = "Just for performance testing")] 7 | //public void NewIsQuicker() { 8 | // var dialect = new SqlServer2012Dialect(); 9 | // var config = MakeConfig(); 10 | // var i = 0; 11 | // Expression> expr = p => p.PostId == i; 12 | // var sw2 = new Stopwatch(); 13 | // for (; i < 1000; i++) { 14 | // sw2.Start(); 15 | // var newWhereClauseWriter = new WhereClauseWriterNew(dialect, config); 16 | // var result = newWhereClauseWriter.GenerateSql(new[] { expr }, null); 17 | // sw2.Stop(); 18 | // } 19 | 20 | // i = 0; 21 | // var sw = new Stopwatch(); 22 | // for (; i < 1000; i++) { 23 | // sw.Start(); 24 | // var whereClauseWriter = new WhereClauseWriter(dialect, config); 25 | // var result = whereClauseWriter.GenerateSql(new[] { expr }, null); 26 | // sw.Stop(); 27 | // } 28 | 29 | // Console.WriteLine(sw.ElapsedTicks); 30 | // Console.WriteLine(sw2.ElapsedTicks); 31 | // Assert.True(sw2.ElapsedTicks < sw.ElapsedTicks); 32 | //} 33 | 34 | private static IConfiguration MakeConfig() { 35 | return new CustomConfig(); 36 | } 37 | 38 | private class CustomConfig : MockConfiguration { 39 | public CustomConfig() { 40 | this.AddNamespaceOf(); 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Dashing/Engine/DML/DeleteWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Dashing.Engine.DML { 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | using Dapper; 8 | 9 | using Dashing.Configuration; 10 | using Dashing.Engine.Dialects; 11 | 12 | internal class DeleteWriter : BaseWriter, IDeleteWriter { 13 | public DeleteWriter(ISqlDialect dialect, IConfiguration config) 14 | : base(dialect, config) { 15 | } 16 | 17 | public SqlWriterResult GenerateSql(IEnumerable entities) { 18 | var entitiesArray = entities as T[] ?? entities.ToArray(); 19 | 20 | if (!entitiesArray.Any()) { 21 | throw new ArgumentOutOfRangeException("entities", "Entities does not contain any members"); 22 | } 23 | 24 | var map = this.Configuration.GetMap(); 25 | var sql = new StringBuilder(); 26 | var paramIdx = 0; 27 | var parameters = new DynamicParameters(); 28 | 29 | sql.Append("delete from "); 30 | this.Dialect.AppendQuotedTableName(sql, map); 31 | sql.Append(" where "); 32 | this.Dialect.AppendQuotedName(sql, map.PrimaryKey.DbName); 33 | sql.Append(" in ("); 34 | 35 | foreach (var entity in entitiesArray) { 36 | var paramName = "@p_" + ++paramIdx; 37 | sql.Append(paramName); 38 | sql.Append(", "); 39 | parameters.Add(paramName, map.GetPrimaryKeyValue(entity)); 40 | } 41 | 42 | sql.Remove(sql.Length - 2, 2); // remove trailing , 43 | sql.Append(")"); 44 | 45 | return new SqlWriterResult(sql.ToString(), parameters); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /docs/configuration-basics.md: -------------------------------------------------------------------------------- 1 | --- 2 | configuration: true 3 | --- 4 | 5 | # Basics 6 | 7 | Your IConfiguration provides information regarding which classes are in your domain and how those classes 8 | are mapped to the database. 9 | 10 | Assuming you're inheriting from BaseConfiguration you'll be able to access the 11 | Add, AddNamespaceOf and Setup methods from within your constructor. These methods allow you to quickly 12 | add the domain classes. Note, that they will only be added once, irrespective of how many times the 13 | method is called. 14 | 15 | Setup() 16 | --------------- 17 | 18 | Add and AddNamespaceOf are very simple, just telling your Configuration that a class should be mapped 19 | by convention. 20 | 21 | Setup, on the otherhand* allows you to modify the mapping. Setup() returns the IMap for the table 22 | which then gives you access to the Columns, Indexes, Foreign Keys as well as Table specific properties 23 | (such as Name, Schema) 24 | 25 | We suggest following intellisense to see what can be achieved but some common examples that we always 26 | seem to perform are: 27 | 28 | ### Setting Max Length on a String Column 29 | 30 | this.Setup().Property(f => f.Content).MaxLength(); 31 | 32 | ### Ignoring a Property as it's not persisted to the database 33 | 34 | this.Setup().Property(f => f.Total).Ignore(); 35 | 36 | ### Adding an Index 37 | 38 | this.Setup().Index(a => new { a.EmailAddress }); 39 | 40 | ### Adding a multi-column Index 41 | 42 | this.Setup().Index(a => new { a.FirstName, a.Surname }); 43 | 44 | ### Adding a unique Index 45 | 46 | this.Setup().Index(a => new { a.EmailAddress }, true); 47 | 48 | ### Changing a table name 49 | 50 | this.Setup().Table("Todos") 51 | 52 | \* Setup calls Add internally -------------------------------------------------------------------------------- /Dashing/Dashing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dashing 5 | Dashing is a simple to use mini ORM built on top of Dapper. It aims to provide fantastic productivity whilst not sacrificing (too much) performance. 6 | Polylytics 7 | Polylytics 8 | https://github.com/Polylytics/dashing 9 | http://polylytics.com/dashing/dashing-icon.png 10 | dashing-icon.png 11 | false 12 | © Polylytics Limited, 2018 13 | en-GB 14 | dashing dapper orm sql mini-orm 15 | net46;netstandard2.1 16 | Dashing 17 | true 18 | true 19 | snupkg 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | $(DefineConstants);COREFX 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | --------------------------------------------------------------------------------