diff --git a/CommandRunner/CodeGeneration/Subsystems/TableRetrievalStatics.cs b/CommandRunner/CodeGeneration/Subsystems/TableRetrievalStatics.cs index 5319945..d500f26 100644 --- a/CommandRunner/CodeGeneration/Subsystems/TableRetrievalStatics.cs +++ b/CommandRunner/CodeGeneration/Subsystems/TableRetrievalStatics.cs @@ -176,23 +176,27 @@ internal static void WritePartialClass( DBConnection cn, string libraryBasePath, private static void writeCacheClass( DBConnection cn, TextWriter writer, IDatabase database, Table table, TableColumns tableColumns, bool isRevisionHistoryTable ) { var cacheKey = table.Name.TableNameToPascal( cn ) + "TableRetrieval"; - var pkTupleTypeArguments = getPkTupleTypeArguments( tableColumns ); writer.WriteLine( "private partial class Cache {" ); + // We use a struct here as the key to the cache. Comparisons are easy/fast and it doesn't have a limit of 7 like Tuples do. + writer.WriteLine( "internal struct Key {" ); + writer.WriteLine( getPkStructMembers( tableColumns ) ); + writer.WriteLine( "}" ); // Key struct. + writer.WriteLine( "internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( \"" + cacheKey + "\", () => new Cache() ); } }" ); writer.WriteLine( "private readonly TableRetrievalQueryCache queries = new TableRetrievalQueryCache();" ); writer.WriteLine( - $"private readonly Dictionary<{TypeNames.Tuple}<{pkTupleTypeArguments}>, Row> rowsByPk = new Dictionary<{TypeNames.Tuple}<{pkTupleTypeArguments}>, Row>();" ); + $"private readonly Dictionary rowsByPk = new Dictionary();" ); if( isRevisionHistoryTable ) { writer.WriteLine( - $"private readonly Dictionary<{TypeNames.Tuple}<{pkTupleTypeArguments}>, Row> latestRevisionRowsByPk = new Dictionary<{TypeNames.Tuple}<{pkTupleTypeArguments}>, Row>();" ); + $"private readonly Dictionary latestRevisionRowsByPk = new Dictionary();" ); } writer.WriteLine( "private Cache() {}" ); writer.WriteLine( "internal TableRetrievalQueryCache Queries => queries; " ); - writer.WriteLine( $"internal Dictionary<{TypeNames.Tuple}<" + pkTupleTypeArguments + ">, Row> RowsByPk => rowsByPk;" ); + writer.WriteLine( $"internal Dictionary RowsByPk => rowsByPk;" ); if( isRevisionHistoryTable ) { - writer.WriteLine( $"internal Dictionary<{TypeNames.Tuple}<" + pkTupleTypeArguments + ">, Row> LatestRevisionRowsByPk { get { return latestRevisionRowsByPk; } }" ); + writer.WriteLine( "internal Dictionary LatestRevisionRowsByPk { get { return latestRevisionRowsByPk; } }" ); } writer.WriteLine( "}" ); @@ -228,14 +232,14 @@ private static void writeGetRowsMethod( writer.WriteLine( "var cache = Cache.Current;" ); var pkConditionVariableNames = tableColumns.KeyColumns.Select( i => i.CamelCasedName + "Condition" ); + var newKeyStructObject = "new Cache.Key {" + StringTools.ConcatenateWithDelimiter( ", ", tableColumns.KeyColumns.Select( kc => $"{kc.PascalCasedName} = {kc.CamelCasedName}Condition.Value" ) ) + "}"; writer.WriteLine( "var isPkQuery = " + StringTools.ConcatenateWithDelimiter( " && ", pkConditionVariableNames.Select( i => i + " != null" ).ToArray() ) + " && conditions.Count() == " + tableColumns.KeyColumns.Count() + ";" ); writer.WriteLine( "if( isPkQuery ) {" ); writer.WriteLine( "Row row;" ); writer.WriteLine( - "if( cache." + ( excludePreviousRevisions ? "LatestRevision" : "" ) + $"RowsByPk.TryGetValue( {TypeNames.Tuple}.Create( " + - StringTools.ConcatenateWithDelimiter( ", ", pkConditionVariableNames.Select( i => i + ".Value" ).ToArray() ) + " ), out row ) )" ); + "if( cache." + ( excludePreviousRevisions ? "LatestRevision" : "" ) + $"RowsByPk.TryGetValue( {newKeyStructObject}, out row ) )" ); writer.WriteLine( "return new [] {row};" ); writer.WriteLine( "}" ); @@ -291,11 +295,11 @@ private static void writeGetRowMatchingPkMethod( writer.WriteLine( "} );" ); var rowsByPkExpression = $"cache.{( isRevisionHistoryTable ? "LatestRevision" : "" )}RowsByPk"; - var pkTupleCreationArguments = pkIsId ? id : StringTools.ConcatenateWithDelimiter( ", ", tableColumns.KeyColumns.Select( i => i.CamelCasedName ) ); + var newKeyStructObject = "new Cache.Key {" + StringTools.ConcatenateWithDelimiter( ", ", tableColumns.KeyColumns.Select( kc => $"{kc.PascalCasedName} = { ( pkIsId ? "id" : kc.CamelCasedName )}" ) ) + "}"; writer.WriteLine( $"if( !{returnNullIfNoMatch} )" ); - writer.WriteLine( $"return {rowsByPkExpression}[ {TypeNames.Tuple}.Create( {pkTupleCreationArguments} ) ];" ); + writer.WriteLine( $"return {rowsByPkExpression}[ {newKeyStructObject} ];" ); writer.WriteLine( "Row row;" ); - writer.WriteLine( $"return {rowsByPkExpression}.TryGetValue( {TypeNames.Tuple}.Create( {pkTupleCreationArguments} ), out row ) ? row : null;" ); + writer.WriteLine( $"return {rowsByPkExpression}.TryGetValue( {newKeyStructObject}, out row ) ? row : null;" ); } else { var condition = pkIsId @@ -397,11 +401,10 @@ cn.DatabaseInfo is OracleInfo // Add all results to RowsByPk. writer.WriteLine( "foreach( var i in results ) {" ); - var pkTupleCreationArgs = tableColumns.KeyColumns.Select( i => "i." + Utility.GetCSharpIdentifier( i.PascalCasedNameExceptForOracle ) ); - var pkTuple = "System.Tuple.Create( " + StringTools.ConcatenateWithDelimiter( ", ", pkTupleCreationArgs.ToArray() ) + " )"; - writer.WriteLine( $"cache.RowsByPk[ {pkTuple} ] = i;" ); + var newKeyStructObject = "new Cache.Key {" + StringTools.ConcatenateWithDelimiter( ", ", tableColumns.KeyColumns.Select( kc => $"{kc.PascalCasedName} = i.{kc.PascalCasedName}" ) ) + "}"; + writer.WriteLine( $"cache.RowsByPk[ {newKeyStructObject} ] = i;" ); if( excludesPreviousRevisions ) - writer.WriteLine( $"cache.LatestRevisionRowsByPk[ {pkTuple} ] = i;" ); + writer.WriteLine( $"cache.LatestRevisionRowsByPk[ {newKeyStructObject} ] = i;" ); writer.WriteLine( "}" ); writer.WriteLine( "return results;" ); @@ -416,6 +419,7 @@ private static string getInlineSelectExpression( private static string getCommandConditionAddingStatement( string commandName ) => $"foreach( var i in commandConditions ) {commandName}.AddCondition( i );"; + // GMS NOTE: Really unsure of the RowVersion feature in TDL and whether or not it should be stripped out. If we keep it it needs much more testing/support. private static string getPkAndVersionTupleTypeArguments( DBConnection cn, TableColumns tableColumns ) => "{0}, {1}".FormatWith( getPkTupleTypeArguments( tableColumns ), cn.DatabaseInfo is OracleInfo ? oracleRowVersionDataType : tableColumns.RowVersionColumn.DataTypeName ); @@ -423,6 +427,10 @@ private static string getPkTupleTypeArguments( TableColumns tableColumns ) { return StringTools.ConcatenateWithDelimiter( ", ", tableColumns.KeyColumns.Select( i => i.DataTypeName ).ToArray() ); } + private static string getPkStructMembers( TableColumns tableColumns ) { + return StringTools.ConcatenateWithDelimiter( Environment.NewLine, tableColumns.KeyColumns.Select( i => $"internal {i.DataTypeName} {i.PascalCasedName};" ).ToArray() ); + } + private static void writeToIdDictionaryMethod( TextWriter writer, TableColumns tableColumns ) { writer.WriteLine( "public static Dictionary<" + tableColumns.KeyColumns.Single().DataTypeName + ", Row> ToIdDictionary( this IEnumerable rows ) {" ); writer.WriteLine( "return rows.ToDictionary( i => i." + Utility.GetCSharpIdentifier( tableColumns.KeyColumns.Single().PascalCasedNameExceptForOracle ) + " );" ); diff --git a/CommandRunner/Program.cs b/CommandRunner/Program.cs index 17802b2..64ccb53 100644 --- a/CommandRunner/Program.cs +++ b/CommandRunner/Program.cs @@ -12,9 +12,13 @@ using TypedDataLayer.Tools; namespace CommandRunner { - class Program { - static int Main( string[] args ) { - var log = new Logger( args.Any( a => a == "-debug" ) ); + public class Program { + /// + /// Loads config and always runs UpdateDependentLogic. + /// + public static int Main( string[] args ) { + var debug = args.Any( a => a == "-debug" ); + var log = new Logger( debug ); if( args.Any( a => a == "-attachDebugger" ) ) { log.Info( "Waiting 15s for debugger" ); @@ -24,15 +28,16 @@ static int Main( string[] args ) { } log.Debug( "TypedDataLayer version " + Assembly.GetExecutingAssembly().GetName().Version ); - log.Debug( "args: " + string.Join( " ", args ) ); - var command = args[ 0 ]; var workingDirectory = Environment.CurrentDirectory; + return LoadConfigAndRunUpdateAllDependentLogic( workingDirectory, debug ); + } + public static int LoadConfigAndRunUpdateAllDependentLogic( string workingDirectory, bool debug ) { + var log = new Logger( debug ); log.Debug( "Executing directory: " + AppDomain.CurrentDomain.BaseDirectory ); log.Info( "Current working directory: " + workingDirectory ); - log.Info( "Running " + command ); var sw = new Stopwatch(); try { diff --git a/TdlTestFp/App.config b/TdlTestFp/App.config new file mode 100644 index 0000000..feecaf2 --- /dev/null +++ b/TdlTestFp/App.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/TdlTestFp/CreateTestDb.sql b/TdlTestFp/CreateTestDb.sql new file mode 100644 index 0000000..e451b12 --- /dev/null +++ b/TdlTestFp/CreateTestDb.sql @@ -0,0 +1,37 @@ +CREATE DATABASE TdlTest +GO + +USE TdlTest +GO +ALTER DATABASE TdlTest SET PAGE_VERIFY CHECKSUM +ALTER DATABASE TdlTest SET AUTO_CREATE_STATISTICS ON (INCREMENTAL = ON) +ALTER DATABASE TdlTest SET AUTO_UPDATE_STATISTICS_ASYNC ON +ALTER DATABASE TdlTest SET ALLOW_SNAPSHOT_ISOLATION ON +ALTER DATABASE TdlTest SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE +GO + +CREATE TABLE GlobalInts( + ParameterName varchar( 50 ) + NOT NULL + CONSTRAINT GlobalIntsPk PRIMARY KEY, + ParameterValue int + NOT NULL +) + +INSERT INTO GlobalInts VALUES( 'LineMarker', 0 ) +GO + +CREATE SEQUENCE PrimarySequence AS int start with 1; +GO + +CREATE TABLE States ( + StateId int NOT NULL CONSTRAINT pkStates PRIMARY KEY, + StateName nvarchar( 50 ) NOT NULL CONSTRAINT uniqueStateName UNIQUE, + Abbreviation nvarchar( 2 ) NOT NULL CONSTRAINT uniqueStateAbbr UNIQUE +) +GO +INSERT INTO States VALUES( 1, 'Alabama', 'AL' ); +INSERT INTO States VALUES( 2, 'Alaska', 'AK' ); +INSERT INTO States VALUES( 3, 'Arizona', 'AZ' ); +INSERT INTO States VALUES( 4, 'Arkansas', 'AR' ); +GO \ No newline at end of file diff --git a/TdlTestFp/Program.cs b/TdlTestFp/Program.cs new file mode 100644 index 0000000..005cd83 --- /dev/null +++ b/TdlTestFp/Program.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TdlTestFp { + class Program { + static void Main( string[] args ) { + Debug.WriteLine( "Hello World!" ); + CommandRunner.Program.LoadConfigAndRunUpdateAllDependentLogic( @"C:\GitHub\TypedDataLayer\TdlTestFp", true ); + } + } +} diff --git a/TdlTestFp/Properties/AssemblyInfo.cs b/TdlTestFp/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d4fd76a --- /dev/null +++ b/TdlTestFp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "TdlTestFp" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "" )] +[assembly: AssemblyProduct( "TdlTestFp" )] +[assembly: AssemblyCopyright( "Copyright © 2020" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "634b4b52-ba61-4cb5-bc77-1ceaac391e72" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/TdlTestFp/Readme.txt b/TdlTestFp/Readme.txt new file mode 100644 index 0000000..4502abf --- /dev/null +++ b/TdlTestFp/Readme.txt @@ -0,0 +1,5 @@ +This test project is not central to the design or function of the TDL tool. + +This test project should not need to build in order to use/deploy/modify TDL. + +This test project should not fail to build just because the machine does not have the/a test database. The dev should not be obligated to create a test database. \ No newline at end of file diff --git a/TdlTestFp/TdlTestFp.csproj b/TdlTestFp/TdlTestFp.csproj new file mode 100644 index 0000000..67a2f79 --- /dev/null +++ b/TdlTestFp/TdlTestFp.csproj @@ -0,0 +1,78 @@ + + + + + Debug + AnyCPU + {634B4B52-BA61-4CB5-BC77-1CEAAC391E72} + Exe + TdlTestFp + TdlTestFp + v4.6.1 + 512 + true + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + x64 + bin\x64\Debug\ + + + x64 + bin\x64\Release\ + + + + + + + + + + + + + + + + + + + + + + {a81039df-def4-40b8-a770-6dd3450e0961} + CommandRunner + + + {86a9c472-70ea-4dd1-b36e-5276c754e720} + TypedDataLayer + + + + + + + + + \ No newline at end of file diff --git a/TdlTestFp/TypedDataLayer/Configuration.xml b/TdlTestFp/TypedDataLayer/Configuration.xml new file mode 100644 index 0000000..276daf2 --- /dev/null +++ b/TdlTestFp/TypedDataLayer/Configuration.xml @@ -0,0 +1,25 @@ + + +Tdl.Tester + + data source=(local);Initial Catalog=TdlTest;Integrated Security=SSPI; + + + 5 + + + + +
dbo.States
+ + + + SELECT NEXT VALUE FOR PrimarySequence as Id + + + + + +
+
\ No newline at end of file diff --git a/TdlTestFp/TypedDataLayer/GeneratedCode/TypedDataLayer.cs b/TdlTestFp/TypedDataLayer/GeneratedCode/TypedDataLayer.cs new file mode 100644 index 0000000..682450b --- /dev/null +++ b/TdlTestFp/TypedDataLayer/GeneratedCode/TypedDataLayer.cs @@ -0,0 +1,1214 @@ +using System; +using System.Globalization; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Diagnostics; +using System.Linq; +using TypedDataLayer; +using TypedDataLayer.Tools; +using TypedDataLayer.Exceptions; +using TypedDataLayer.DatabaseSpecification; +using TypedDataLayer.DatabaseSpecification.Databases; +using TypedDataLayer.DataAccess; +using TypedDataLayer.DataAccess.StandardModification; +using TypedDataLayer.DataAccess.RetrievalCaching; +using TypedDataLayer.DataAccess.CommandWriting; +using TypedDataLayer.DataAccess.CommandWriting.InlineConditionAbstraction; +using TypedDataLayer.DataAccess.CommandWriting.InlineConditionAbstraction.Conditions; +using TypedDataLayer.DataAccess.CommandWriting.Commands; +using TypedDataLayer.Containers; +using TypedDataLayer.Collections; + +namespace Tdl.Tester.DataAccess { +public static class Configuration { +public const int CommandTimeoutSeconds = 5; +} +} + +namespace Tdl.Tester.DataAccess.TableConstants { +namespace dbo { +/// +/// This object represents the constants of the CommandRunner.DatabaseAbstraction.Table table. +/// +public class @GlobalIntsTable { +/// +/// The name of this table. +/// +public const string Name = "CommandRunner.DatabaseAbstraction.Table"; +/// +/// Contains schema information about this column. +/// +public class @ParameterNameColumn { +/// +/// The name of this column. +/// +public const string Name = "ParameterName"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 50; +} +/// +/// Contains schema information about this column. +/// +public class @ParameterValueColumn { +/// +/// The name of this column. +/// +public const string Name = "ParameterValue"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 4; +} +} +} +namespace dbo { +/// +/// This object represents the constants of the CommandRunner.DatabaseAbstraction.Table table. +/// +public class @StatesTable { +/// +/// The name of this table. +/// +public const string Name = "CommandRunner.DatabaseAbstraction.Table"; +/// +/// Contains schema information about this column. +/// +public class @StateIdColumn { +/// +/// The name of this column. +/// +public const string Name = "StateId"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 4; +} +/// +/// Contains schema information about this column. +/// +public class @StateNameColumn { +/// +/// The name of this column. +/// +public const string Name = "StateName"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 50; +} +/// +/// Contains schema information about this column. +/// +public class @AbbreviationColumn { +/// +/// The name of this column. +/// +public const string Name = "Abbreviation"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 2; +} +} +} +} + +namespace Tdl.Tester.DataAccess.RowConstants { +namespace dbo { +/// +/// Provides constants copied from the dbo.States table. +/// +public class StatesRows { +/// +/// Constant generated from row in database table. +/// +public const int @Ak = 2; +/// +/// Constant generated from row in database table. +/// +public const int @Al = 1; +/// +/// Constant generated from row in database table. +/// +public const int @Ar = 4; +/// +/// Constant generated from row in database table. +/// +public const int @Az = 3; +private static readonly OneToOneMap valuesAndNames = new OneToOneMap(); +static StatesRows() { +valuesAndNames.Add( (int)(2), "AK" ); +valuesAndNames.Add( (int)(1), "AL" ); +valuesAndNames.Add( (int)(4), "AR" ); +valuesAndNames.Add( (int)(3), "AZ" ); +} +/// +/// Returns the name of the constant given the constant's value. +/// +public static string GetNameFromValue( int constantValue ) { +return valuesAndNames.GetRightFromLeft( constantValue ); +} +/// +/// Returns the value of the constant given the constant's name. +/// +public static int GetValueFromName( string constantName ) { +return valuesAndNames.GetLeftFromRight( constantName ); +} +} +} +} + +namespace Tdl.Tester.DataAccess.CommandConditions { +namespace dbo { +public interface GlobalIntsTableCondition: TableCondition {} +public static class @GlobalIntsTableEqualityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( value, "VarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( int value ) { +this.value = value; +} +internal int Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( value, "Int" ) ) ); } } +} +} +public static class @GlobalIntsTableInequalityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @ParameterName( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( value, "VarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly InequalityCondition.Operator op; +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @ParameterValue( InequalityCondition.Operator op, int value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( value, "Int" ) ) ); } } +} +} +public static class @GlobalIntsTableInConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "ParameterName", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "ParameterValue", subQuery ); } } +} +} +public static class @GlobalIntsTableLikeConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "ParameterName", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "ParameterValue", value ); } } +} +} +} +namespace dbo { +public interface StatesTableCondition: TableCondition {} +public static class @StatesTableEqualityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( int value ) { +this.value = value; +} +internal int Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "StateId", new DbParameterValue( value, "Int" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "StateName", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +} +public static class @StatesTableInequalityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @StateId( InequalityCondition.Operator op, int value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "StateId", new DbParameterValue( value, "Int" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @StateName( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "StateName", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @Abbreviation( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +} +public static class @StatesTableInConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "StateId", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "StateName", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "Abbreviation", subQuery ); } } +} +} +public static class @StatesTableLikeConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "StateId", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "StateName", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "Abbreviation", value ); } } +} +} +} +} + +namespace Tdl.Tester.DataAccess.TableRetrieval { +/// +/// Contains logic that retrieves rows from the CommandRunner.DatabaseAbstraction.Table table. +/// +namespace dbo { +public static partial class @GlobalIntsTableRetrieval { +internal class BasicRow { +private readonly string @__parameterName; +private readonly int @__parameterValue; +internal BasicRow( DbDataReader reader ) { +@__parameterName = (string)reader.GetValue( 0 ); +@__parameterValue = (int)reader.GetValue( 1 ); +} +internal string @ParameterName { get { return @__parameterName; } } +internal int @ParameterValue { get { return @__parameterValue; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public string @ParameterName { get { return __basicRow.@ParameterName; } } +/// +/// This object will never be null. +/// +public int @ParameterValue { get { return __basicRow.@ParameterValue; } } +public override int GetHashCode() { +return @ParameterName.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @ParameterName == other.@ParameterName && @ParameterValue == other.@ParameterValue; +} +public Modification.dbo.@GlobalIntsModification ToModification() { +return Modification.dbo.@GlobalIntsModification.CreateForSingleRowUpdate( @ParameterName, @ParameterValue ); +} +} +private partial class Cache { +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "GlobalIntsTableRetrieval", () => new Cache() ); } } +private readonly TableRetrievalQueryCache queries = new TableRetrievalQueryCache(); +private readonly Dictionary, Row> rowsByPk = new Dictionary, Row>(); +private Cache() {} +internal TableRetrievalQueryCache Queries => queries; +internal Dictionary, Row> RowsByPk => rowsByPk; +} +/// +/// Retrieves the rows from the table that match the specified conditions, ordered in a stable way. +/// +public static IEnumerable GetRows( params CommandConditions.dbo.GlobalIntsTableCondition[] conditions ) { +var parameterNameCondition = conditions.OfType().FirstOrDefault(); +var cache = Cache.Current; +var isPkQuery = parameterNameCondition != null && conditions.Count() == 1; +if( isPkQuery ) { +Row row; +if( cache.RowsByPk.TryGetValue( Tuple.Create( parameterNameCondition.Value ), out row ) ) +return new [] {row}; +} +return cache.Queries.GetResultSet( conditions.Select( i => i.CommandCondition ), commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.GlobalInts", !isPkQuery, 5, orderByClause: "ORDER BY ParameterName" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ System.Tuple.Create( i.@ParameterName ) ] = i; +} +return results; +} ); +} +public static Row GetRowMatchingPk( string parameterName, bool returnNullIfNoMatch = false ) { +return GetRows( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( parameterName ) ).PrimaryKeySingle(returnNullIfNoMatch); +} +} +} +/// +/// Contains logic that retrieves rows from the CommandRunner.DatabaseAbstraction.Table table. +/// +namespace dbo { +public static partial class @StatesTableRetrieval { +internal class BasicRow { +private readonly int @__stateId; +private readonly string @__stateName; +private readonly string @__abbreviation; +internal BasicRow( DbDataReader reader ) { +@__stateId = (int)reader.GetValue( 0 ); +@__stateName = (string)reader.GetValue( 1 ); +@__abbreviation = (string)reader.GetValue( 2 ); +} +internal int @StateId { get { return @__stateId; } } +internal string @StateName { get { return @__stateName; } } +internal string @Abbreviation { get { return @__abbreviation; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public int @StateId { get { return __basicRow.@StateId; } } +/// +/// This object will never be null. +/// +public string @StateName { get { return __basicRow.@StateName; } } +/// +/// This object will never be null. +/// +public string @Abbreviation { get { return __basicRow.@Abbreviation; } } +public override int GetHashCode() { +return @StateId.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @StateId == other.@StateId && @StateName == other.@StateName && @Abbreviation == other.@Abbreviation; +} +public Modification.dbo.@StatesModification ToModification() { +return Modification.dbo.@StatesModification.CreateForSingleRowUpdate( @StateId, @StateName, @Abbreviation ); +} +} +private partial class Cache { +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "StatesTableRetrieval", () => new Cache() ); } } +private readonly TableRetrievalQueryCache queries = new TableRetrievalQueryCache(); +private readonly Dictionary, Row> rowsByPk = new Dictionary, Row>(); +private Cache() {} +internal TableRetrievalQueryCache Queries => queries; +internal Dictionary, Row> RowsByPk => rowsByPk; +} +/// +/// Retrieves the rows from the table, ordered in a stable way. +/// +public static IEnumerable GetAllRows() { +return GetRowsMatchingConditions(); +} +/// +/// Retrieves the rows from the table that match the specified conditions, ordered in a stable way. Since the table is specified as small, you should only use this method if you cannot filter the rows in code. +/// +public static IEnumerable GetRowsMatchingConditions( params CommandConditions.dbo.StatesTableCondition[] conditions ) { +var stateIdCondition = conditions.OfType().FirstOrDefault(); +var cache = Cache.Current; +var isPkQuery = stateIdCondition != null && conditions.Count() == 1; +if( isPkQuery ) { +Row row; +if( cache.RowsByPk.TryGetValue( Tuple.Create( stateIdCondition.Value ), out row ) ) +return new [] {row}; +} +return cache.Queries.GetResultSet( conditions.Select( i => i.CommandCondition ), commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.States", !isPkQuery, 5, orderByClause: "ORDER BY StateId" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ System.Tuple.Create( i.@StateId ) ] = i; +} +return results; +} ); +} +public static Row GetRowMatchingId( int id, bool returnNullIfNoMatch = false ) { +var cache = Cache.Current; +cache.Queries.GetResultSet( new InlineDbCommandCondition[ 0 ], commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.States", true, 5, orderByClause: "ORDER BY StateId" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ System.Tuple.Create( i.@StateId ) ] = i; +} +return results; +} ); +if( !returnNullIfNoMatch ) +return cache.RowsByPk[ Tuple.Create( id ) ]; +Row row; +return cache.RowsByPk.TryGetValue( Tuple.Create( id ), out row ) ? row : null; +} +public static Dictionary ToIdDictionary( this IEnumerable rows ) { +return rows.ToDictionary( i => i.@StateId ); +} +} +} +} + +namespace Tdl.Tester.DataAccess.Modification { +namespace dbo { +public partial class @GlobalIntsModification { +/// +/// Inserts a row into the dbo.GlobalInts table. +/// +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRow( string @parameterName, int @parameterValue ) { +var mod = CreateForInsert(); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.Execute(); +} +/// +/// Inserts a row into the dbo.GlobalInts table. +/// +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRowWithoutAdditionalLogic( string @parameterName, int @parameterValue ) { +var mod = CreateForInsert(); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Updates rows in the dbo.GlobalInts table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRows( string @parameterName, int @parameterValue, CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.Execute(); +} +/// +/// Updates rows in the dbo.GlobalInts table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRowsWithoutAdditionalLogic( string @parameterName, int @parameterValue, CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRows( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +return DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var conditions = getConditionList( requiredCondition, additionalConditions ); +PostDeleteCall> postDeleteCall = null; +preDelete( conditions, ref postDeleteCall ); +var rowsDeleted = deleteRows( conditions ); +if( postDeleteCall != null ) +postDeleteCall.Execute(); +return rowsDeleted; +} ); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRowsWithoutAdditionalLogic( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var conditions = getConditionList( requiredCondition, additionalConditions ); +var rowsDeleted = deleteRows( conditions ); +return rowsDeleted; +} +private static int deleteRows( List conditions ) { +var delete = new InlineDelete( "dbo.GlobalInts", 5 ); +conditions.ForEach( condition => delete.AddCondition( condition.CommandCondition ) ); +try { +return delete.Execute( DataAccessState.Current.DatabaseConnection ); +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +static partial void preDelete( List conditions, ref PostDeleteCall> postDeleteCall ); +private ModificationType modType; +private List conditions; +private readonly DataValue @parameterNameColumnValue = new DataValue(); +/// +/// Gets or sets the value for the ParameterName column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @ParameterName { get { return @parameterNameColumnValue.Value; } set { @parameterNameColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the ParameterName has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @ParameterNameHasChanged { get { return @parameterNameColumnValue.Changed; } } +private readonly DataValue @parameterValueColumnValue = new DataValue(); +/// +/// Gets or sets the value for the ParameterValue column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public int @ParameterValue { get { return @parameterValueColumnValue.Value; } set { @parameterValueColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the ParameterValue has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @ParameterValueHasChanged { get { return @parameterValueColumnValue.Changed; } } +/// +/// Creates a modification object in insert mode, which can be used to do a piecemeal insert of a new row in the CommandRunner.DatabaseAbstraction.Table table. +/// +public static dbo.@GlobalIntsModification CreateForInsert() { +return new dbo.@GlobalIntsModification { modType = ModificationType.Insert }; +} +/// +/// Creates a modification object in update mode with the specified conditions, which can be used to do a piecemeal update of the dbo.GlobalInts table. +/// +public static dbo.@GlobalIntsModification CreateForUpdate( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = new dbo.@GlobalIntsModification { modType = ModificationType.Update, conditions = getConditionList( requiredCondition, additionalConditions ) }; +foreach( var condition in mod.conditions ) { +if( condition is CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName ) +mod.@parameterNameColumnValue.Value = ( condition as CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName ).Value; +else if( condition is CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterValue ) +mod.@parameterValueColumnValue.Value = ( condition as CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterValue ).Value; +} + +mod.markColumnValuesUnchanged(); +return mod; +} +/// +/// Creates a modification object in single-row update mode with the specified current data. All column values in this object will have HasChanged = false, despite being initialized. This object can then be used to do a piecemeal update of the dbo.GlobalInts table. +/// +public static dbo.@GlobalIntsModification CreateForSingleRowUpdate( string @parameterName, int @parameterValue ) { +var mod = new dbo.@GlobalIntsModification { modType = ModificationType.Update }; +mod.conditions = new List(); +mod.conditions.Add( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( @parameterName ) ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.markColumnValuesUnchanged(); +return mod; +} +private static List getConditionList( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var conditions = new List(); +conditions.Add( requiredCondition ); +foreach( var condition in additionalConditions ) +conditions.Add( condition ); +return conditions; +} +private @GlobalIntsModification() {} +/// +/// Sets all column values. This is useful for enforcing the number of arguments when deferred execution is needed. +/// +/// Object does not allow null. +/// Object does not allow null. +public void SetAllData( string @parameterName, int @parameterValue ) { +this.@parameterNameColumnValue.Value = @parameterName; +this.@parameterValueColumnValue.Value = @parameterValue; +} +/// +/// Executes this dbo.GlobalInts modification, persisting all changes. Executes any pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void Execute() { +DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var frozenModType = modType; +if( frozenModType == ModificationType.Insert ) +preInsert(); +else if( frozenModType == ModificationType.Update ) +preUpdate(); +executeInsertOrUpdate(); +if( frozenModType == ModificationType.Insert ) +postInsert(); +else if( frozenModType == ModificationType.Update ) +postUpdate(); +markColumnValuesUnchanged(); +} ); +} +partial void preInsert(); +partial void preUpdate(); +/// +/// Executes this dbo.GlobalInts modification, persisting all changes. Does not execute pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void ExecuteWithoutAdditionalLogic() { +executeInsertOrUpdate(); +markColumnValuesUnchanged(); +} +private void executeInsertOrUpdate() { +try { +if( modType == ModificationType.Insert ) { +var insert = new InlineInsert( "dbo.GlobalInts", false, 5 ); +addColumnModifications( insert ); +insert.Execute( DataAccessState.Current.DatabaseConnection ); +if( !@ParameterNameHasChanged ) return; +modType = ModificationType.Update; +conditions = new List(); +conditions.Add( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( @ParameterName ) ); +} +else { +var update = new InlineUpdate( "dbo.GlobalInts", 5 ); +addColumnModifications( update ); +conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) ); +update.Execute( DataAccessState.Current.DatabaseConnection ); +} +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +private void addColumnModifications( InlineDbModificationCommand cmd ) { +if( @parameterNameColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( @ParameterName, "VarChar" ) ) ); +if( @parameterValueColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( @ParameterValue, "Int" ) ) ); +} +private static void rethrowAsDataModificationExceptionIfNecessary( System.Exception e ) { +var constraintNamesToViolationErrorMessages = new Dictionary(); +populateConstraintNamesToViolationErrorMessages( constraintNamesToViolationErrorMessages ); +foreach( var pair in constraintNamesToViolationErrorMessages ) +if( e.GetBaseException().Message.ToLower().Contains( pair.Key.ToLower() ) ) throw new DataModificationException( pair.Value ); +} +static partial void populateConstraintNamesToViolationErrorMessages( Dictionary constraintNamesToViolationErrorMessages ); +partial void postInsert(); +partial void postUpdate(); +private void markColumnValuesUnchanged() { +@parameterNameColumnValue.ClearChanged(); +@parameterValueColumnValue.ClearChanged(); +} +} +} +namespace dbo { +public partial class @StatesModification { +/// +/// Inserts a row into the dbo.States table. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRow( int @stateId, string @stateName, string @abbreviation ) { +var mod = CreateForInsert(); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.Execute(); +} +/// +/// Inserts a row into the dbo.States table. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRowWithoutAdditionalLogic( int @stateId, string @stateName, string @abbreviation ) { +var mod = CreateForInsert(); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Updates rows in the dbo.States table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRows( int @stateId, string @stateName, string @abbreviation, CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.Execute(); +} +/// +/// Updates rows in the dbo.States table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRowsWithoutAdditionalLogic( int @stateId, string @stateName, string @abbreviation, CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRows( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +return DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var conditions = getConditionList( requiredCondition, additionalConditions ); +PostDeleteCall> postDeleteCall = null; +preDelete( conditions, ref postDeleteCall ); +var rowsDeleted = deleteRows( conditions ); +if( postDeleteCall != null ) +postDeleteCall.Execute(); +return rowsDeleted; +} ); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRowsWithoutAdditionalLogic( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var conditions = getConditionList( requiredCondition, additionalConditions ); +var rowsDeleted = deleteRows( conditions ); +return rowsDeleted; +} +private static int deleteRows( List conditions ) { +var delete = new InlineDelete( "dbo.States", 5 ); +conditions.ForEach( condition => delete.AddCondition( condition.CommandCondition ) ); +try { +return delete.Execute( DataAccessState.Current.DatabaseConnection ); +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +static partial void preDelete( List conditions, ref PostDeleteCall> postDeleteCall ); +private ModificationType modType; +private List conditions; +private readonly DataValue @stateIdColumnValue = new DataValue(); +/// +/// Gets or sets the value for the StateId column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public int @StateId { get { return @stateIdColumnValue.Value; } set { @stateIdColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the StateId has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @StateIdHasChanged { get { return @stateIdColumnValue.Changed; } } +private readonly DataValue @stateNameColumnValue = new DataValue(); +/// +/// Gets or sets the value for the StateName column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @StateName { get { return @stateNameColumnValue.Value; } set { @stateNameColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the StateName has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @StateNameHasChanged { get { return @stateNameColumnValue.Changed; } } +private readonly DataValue @abbreviationColumnValue = new DataValue(); +/// +/// Gets or sets the value for the Abbreviation column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @Abbreviation { get { return @abbreviationColumnValue.Value; } set { @abbreviationColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the Abbreviation has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @AbbreviationHasChanged { get { return @abbreviationColumnValue.Changed; } } +/// +/// Creates a modification object in insert mode, which can be used to do a piecemeal insert of a new row in the CommandRunner.DatabaseAbstraction.Table table. +/// +public static dbo.@StatesModification CreateForInsert() { +return new dbo.@StatesModification { modType = ModificationType.Insert }; +} +/// +/// Creates a modification object in update mode with the specified conditions, which can be used to do a piecemeal update of the dbo.States table. +/// +public static dbo.@StatesModification CreateForUpdate( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = new dbo.@StatesModification { modType = ModificationType.Update, conditions = getConditionList( requiredCondition, additionalConditions ) }; +foreach( var condition in mod.conditions ) { +if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@StateId ) +mod.@stateIdColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@StateId ).Value; +else if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@StateName ) +mod.@stateNameColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@StateName ).Value; +else if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@Abbreviation ) +mod.@abbreviationColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@Abbreviation ).Value; +} + +mod.markColumnValuesUnchanged(); +return mod; +} +/// +/// Creates a modification object in single-row update mode with the specified current data. All column values in this object will have HasChanged = false, despite being initialized. This object can then be used to do a piecemeal update of the dbo.States table. +/// +public static dbo.@StatesModification CreateForSingleRowUpdate( int @stateId, string @stateName, string @abbreviation ) { +var mod = new dbo.@StatesModification { modType = ModificationType.Update }; +mod.conditions = new List(); +mod.conditions.Add( new CommandConditions.dbo.@StatesTableEqualityConditions.@StateId( @stateId ) ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.markColumnValuesUnchanged(); +return mod; +} +private static List getConditionList( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var conditions = new List(); +conditions.Add( requiredCondition ); +foreach( var condition in additionalConditions ) +conditions.Add( condition ); +return conditions; +} +private @StatesModification() {} +/// +/// Sets all column values. This is useful for enforcing the number of arguments when deferred execution is needed. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public void SetAllData( int @stateId, string @stateName, string @abbreviation ) { +this.@stateIdColumnValue.Value = @stateId; +this.@stateNameColumnValue.Value = @stateName; +this.@abbreviationColumnValue.Value = @abbreviation; +} +/// +/// Executes this dbo.States modification, persisting all changes. Executes any pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void Execute() { +DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var frozenModType = modType; +if( frozenModType == ModificationType.Insert ) +preInsert(); +else if( frozenModType == ModificationType.Update ) +preUpdate(); +executeInsertOrUpdate(); +if( frozenModType == ModificationType.Insert ) +postInsert(); +else if( frozenModType == ModificationType.Update ) +postUpdate(); +markColumnValuesUnchanged(); +} ); +} +partial void preInsert(); +partial void preUpdate(); +/// +/// Executes this dbo.States modification, persisting all changes. Does not execute pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void ExecuteWithoutAdditionalLogic() { +executeInsertOrUpdate(); +markColumnValuesUnchanged(); +} +private void executeInsertOrUpdate() { +try { +if( modType == ModificationType.Insert ) { +var insert = new InlineInsert( "dbo.States", false, 5 ); +addColumnModifications( insert ); +insert.Execute( DataAccessState.Current.DatabaseConnection ); +if( !@StateIdHasChanged ) return; +modType = ModificationType.Update; +conditions = new List(); +conditions.Add( new CommandConditions.dbo.@StatesTableEqualityConditions.@StateId( @StateId ) ); +} +else { +var update = new InlineUpdate( "dbo.States", 5 ); +addColumnModifications( update ); +conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) ); +update.Execute( DataAccessState.Current.DatabaseConnection ); +} +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +private void addColumnModifications( InlineDbModificationCommand cmd ) { +if( @stateIdColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "StateId", new DbParameterValue( @StateId, "Int" ) ) ); +if( @stateNameColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "StateName", new DbParameterValue( @StateName, "NVarChar" ) ) ); +if( @abbreviationColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( @Abbreviation, "NVarChar" ) ) ); +} +private static void rethrowAsDataModificationExceptionIfNecessary( System.Exception e ) { +var constraintNamesToViolationErrorMessages = new Dictionary(); +populateConstraintNamesToViolationErrorMessages( constraintNamesToViolationErrorMessages ); +foreach( var pair in constraintNamesToViolationErrorMessages ) +if( e.GetBaseException().Message.ToLower().Contains( pair.Key.ToLower() ) ) throw new DataModificationException( pair.Value ); +} +static partial void populateConstraintNamesToViolationErrorMessages( Dictionary constraintNamesToViolationErrorMessages ); +partial void postInsert(); +partial void postUpdate(); +private void markColumnValuesUnchanged() { +@stateIdColumnValue.ClearChanged(); +@stateNameColumnValue.ClearChanged(); +@abbreviationColumnValue.ClearChanged(); +} +} +} +} + +namespace Tdl.Tester.DataAccess.Retrieval { +/// +/// This object holds the values returned from a PrimarySequence query. +/// +public static partial class PrimarySequenceRetrieval { +internal class BasicRow { +private readonly int @__id; +internal BasicRow( DbDataReader reader ) { +@__id = (int)reader.GetValue( 0 ); +} +internal int @Id { get { return @__id; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public int @Id { get { return __basicRow.@Id; } } +public override int GetHashCode() { +return @Id.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @Id == other.@Id; +} +} +private partial class Cache { +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "PrimarySequenceQueryRetrieval", () => new Cache() ); } } +private readonly ParameterlessQueryCache rowsNextQuery = new ParameterlessQueryCache(); +private Cache() {} +internal ParameterlessQueryCache RowsNextQuery { get { return rowsNextQuery; } } +} +private const string selectFromClause = @"SELECT NEXT VALUE FOR PrimarySequence as Id "; +/// +/// Queries the database and returns the full results collection immediately. +/// +public static IEnumerable GetRowsNext( ) { +return Cache.Current.RowsNextQuery.GetResultSet( () => { +var cmd = DataAccessState.Current.DatabaseConnection.DatabaseInfo.CreateCommand(5); +cmd.CommandText = selectFromClause +;var results = new List(); +DataAccessState.Current.DatabaseConnection.ExecuteReaderCommand( cmd, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) +updateSingleRowCaches( i ); +return results; +} ); +} +static partial void updateSingleRowCaches( Row row ); +} +} + diff --git a/TdlTester/CreateTestDb.sql b/TdlTester/CreateTestDb.sql new file mode 100644 index 0000000..e451b12 --- /dev/null +++ b/TdlTester/CreateTestDb.sql @@ -0,0 +1,37 @@ +CREATE DATABASE TdlTest +GO + +USE TdlTest +GO +ALTER DATABASE TdlTest SET PAGE_VERIFY CHECKSUM +ALTER DATABASE TdlTest SET AUTO_CREATE_STATISTICS ON (INCREMENTAL = ON) +ALTER DATABASE TdlTest SET AUTO_UPDATE_STATISTICS_ASYNC ON +ALTER DATABASE TdlTest SET ALLOW_SNAPSHOT_ISOLATION ON +ALTER DATABASE TdlTest SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE +GO + +CREATE TABLE GlobalInts( + ParameterName varchar( 50 ) + NOT NULL + CONSTRAINT GlobalIntsPk PRIMARY KEY, + ParameterValue int + NOT NULL +) + +INSERT INTO GlobalInts VALUES( 'LineMarker', 0 ) +GO + +CREATE SEQUENCE PrimarySequence AS int start with 1; +GO + +CREATE TABLE States ( + StateId int NOT NULL CONSTRAINT pkStates PRIMARY KEY, + StateName nvarchar( 50 ) NOT NULL CONSTRAINT uniqueStateName UNIQUE, + Abbreviation nvarchar( 2 ) NOT NULL CONSTRAINT uniqueStateAbbr UNIQUE +) +GO +INSERT INTO States VALUES( 1, 'Alabama', 'AL' ); +INSERT INTO States VALUES( 2, 'Alaska', 'AK' ); +INSERT INTO States VALUES( 3, 'Arizona', 'AZ' ); +INSERT INTO States VALUES( 4, 'Arkansas', 'AR' ); +GO \ No newline at end of file diff --git a/TdlTester/Program.cs b/TdlTester/Program.cs new file mode 100644 index 0000000..8d30614 --- /dev/null +++ b/TdlTester/Program.cs @@ -0,0 +1,11 @@ +using System.Diagnostics; + +namespace Tdl.Tester { + class Program { + static void Main( string[] args ) { + // GMS NOTE: The floor effort for loading configuration in .net core is like a hundred lines of code spread across nine fucking files, so hardcoding here for now. + Debug.WriteLine( "Hello World!" ); + CommandRunner.Program.LoadConfigAndRunUpdateAllDependentLogic( @"C:\GitHub\TypedDataLayer\TdlTester", true ); + } + } +} \ No newline at end of file diff --git a/TdlTester/Readme.txt b/TdlTester/Readme.txt new file mode 100644 index 0000000..4502abf --- /dev/null +++ b/TdlTester/Readme.txt @@ -0,0 +1,5 @@ +This test project is not central to the design or function of the TDL tool. + +This test project should not need to build in order to use/deploy/modify TDL. + +This test project should not fail to build just because the machine does not have the/a test database. The dev should not be obligated to create a test database. \ No newline at end of file diff --git a/TdlTester/TdlTester.csproj b/TdlTester/TdlTester.csproj new file mode 100644 index 0000000..5e5e9f8 --- /dev/null +++ b/TdlTester/TdlTester.csproj @@ -0,0 +1,14 @@ + + + + Exe + netcoreapp2.2 + Tdl.Tester + Tdl.Tester + + + + + + + diff --git a/TdlTester/TypedDataLayer/Configuration.xml b/TdlTester/TypedDataLayer/Configuration.xml new file mode 100644 index 0000000..276daf2 --- /dev/null +++ b/TdlTester/TypedDataLayer/Configuration.xml @@ -0,0 +1,25 @@ + + +Tdl.Tester + + data source=(local);Initial Catalog=TdlTest;Integrated Security=SSPI; + + + 5 + + + + +
dbo.States
+ + + + SELECT NEXT VALUE FOR PrimarySequence as Id + + + + + +
+
\ No newline at end of file diff --git a/TdlTester/TypedDataLayer/GeneratedCode/TypedDataLayer.cs b/TdlTester/TypedDataLayer/GeneratedCode/TypedDataLayer.cs new file mode 100644 index 0000000..682450b --- /dev/null +++ b/TdlTester/TypedDataLayer/GeneratedCode/TypedDataLayer.cs @@ -0,0 +1,1214 @@ +using System; +using System.Globalization; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Diagnostics; +using System.Linq; +using TypedDataLayer; +using TypedDataLayer.Tools; +using TypedDataLayer.Exceptions; +using TypedDataLayer.DatabaseSpecification; +using TypedDataLayer.DatabaseSpecification.Databases; +using TypedDataLayer.DataAccess; +using TypedDataLayer.DataAccess.StandardModification; +using TypedDataLayer.DataAccess.RetrievalCaching; +using TypedDataLayer.DataAccess.CommandWriting; +using TypedDataLayer.DataAccess.CommandWriting.InlineConditionAbstraction; +using TypedDataLayer.DataAccess.CommandWriting.InlineConditionAbstraction.Conditions; +using TypedDataLayer.DataAccess.CommandWriting.Commands; +using TypedDataLayer.Containers; +using TypedDataLayer.Collections; + +namespace Tdl.Tester.DataAccess { +public static class Configuration { +public const int CommandTimeoutSeconds = 5; +} +} + +namespace Tdl.Tester.DataAccess.TableConstants { +namespace dbo { +/// +/// This object represents the constants of the CommandRunner.DatabaseAbstraction.Table table. +/// +public class @GlobalIntsTable { +/// +/// The name of this table. +/// +public const string Name = "CommandRunner.DatabaseAbstraction.Table"; +/// +/// Contains schema information about this column. +/// +public class @ParameterNameColumn { +/// +/// The name of this column. +/// +public const string Name = "ParameterName"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 50; +} +/// +/// Contains schema information about this column. +/// +public class @ParameterValueColumn { +/// +/// The name of this column. +/// +public const string Name = "ParameterValue"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 4; +} +} +} +namespace dbo { +/// +/// This object represents the constants of the CommandRunner.DatabaseAbstraction.Table table. +/// +public class @StatesTable { +/// +/// The name of this table. +/// +public const string Name = "CommandRunner.DatabaseAbstraction.Table"; +/// +/// Contains schema information about this column. +/// +public class @StateIdColumn { +/// +/// The name of this column. +/// +public const string Name = "StateId"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 4; +} +/// +/// Contains schema information about this column. +/// +public class @StateNameColumn { +/// +/// The name of this column. +/// +public const string Name = "StateName"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 50; +} +/// +/// Contains schema information about this column. +/// +public class @AbbreviationColumn { +/// +/// The name of this column. +/// +public const string Name = "Abbreviation"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 2; +} +} +} +} + +namespace Tdl.Tester.DataAccess.RowConstants { +namespace dbo { +/// +/// Provides constants copied from the dbo.States table. +/// +public class StatesRows { +/// +/// Constant generated from row in database table. +/// +public const int @Ak = 2; +/// +/// Constant generated from row in database table. +/// +public const int @Al = 1; +/// +/// Constant generated from row in database table. +/// +public const int @Ar = 4; +/// +/// Constant generated from row in database table. +/// +public const int @Az = 3; +private static readonly OneToOneMap valuesAndNames = new OneToOneMap(); +static StatesRows() { +valuesAndNames.Add( (int)(2), "AK" ); +valuesAndNames.Add( (int)(1), "AL" ); +valuesAndNames.Add( (int)(4), "AR" ); +valuesAndNames.Add( (int)(3), "AZ" ); +} +/// +/// Returns the name of the constant given the constant's value. +/// +public static string GetNameFromValue( int constantValue ) { +return valuesAndNames.GetRightFromLeft( constantValue ); +} +/// +/// Returns the value of the constant given the constant's name. +/// +public static int GetValueFromName( string constantName ) { +return valuesAndNames.GetLeftFromRight( constantName ); +} +} +} +} + +namespace Tdl.Tester.DataAccess.CommandConditions { +namespace dbo { +public interface GlobalIntsTableCondition: TableCondition {} +public static class @GlobalIntsTableEqualityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( value, "VarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( int value ) { +this.value = value; +} +internal int Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( value, "Int" ) ) ); } } +} +} +public static class @GlobalIntsTableInequalityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @ParameterName( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( value, "VarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly InequalityCondition.Operator op; +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @ParameterValue( InequalityCondition.Operator op, int value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( value, "Int" ) ) ); } } +} +} +public static class @GlobalIntsTableInConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "ParameterName", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "ParameterValue", subQuery ); } } +} +} +public static class @GlobalIntsTableLikeConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "ParameterName", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "ParameterValue", value ); } } +} +} +} +namespace dbo { +public interface StatesTableCondition: TableCondition {} +public static class @StatesTableEqualityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( int value ) { +this.value = value; +} +internal int Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "StateId", new DbParameterValue( value, "Int" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "StateName", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +} +public static class @StatesTableInequalityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @StateId( InequalityCondition.Operator op, int value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "StateId", new DbParameterValue( value, "Int" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @StateName( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "StateName", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @Abbreviation( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +} +public static class @StatesTableInConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "StateId", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "StateName", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "Abbreviation", subQuery ); } } +} +} +public static class @StatesTableLikeConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "StateId", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "StateName", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "Abbreviation", value ); } } +} +} +} +} + +namespace Tdl.Tester.DataAccess.TableRetrieval { +/// +/// Contains logic that retrieves rows from the CommandRunner.DatabaseAbstraction.Table table. +/// +namespace dbo { +public static partial class @GlobalIntsTableRetrieval { +internal class BasicRow { +private readonly string @__parameterName; +private readonly int @__parameterValue; +internal BasicRow( DbDataReader reader ) { +@__parameterName = (string)reader.GetValue( 0 ); +@__parameterValue = (int)reader.GetValue( 1 ); +} +internal string @ParameterName { get { return @__parameterName; } } +internal int @ParameterValue { get { return @__parameterValue; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public string @ParameterName { get { return __basicRow.@ParameterName; } } +/// +/// This object will never be null. +/// +public int @ParameterValue { get { return __basicRow.@ParameterValue; } } +public override int GetHashCode() { +return @ParameterName.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @ParameterName == other.@ParameterName && @ParameterValue == other.@ParameterValue; +} +public Modification.dbo.@GlobalIntsModification ToModification() { +return Modification.dbo.@GlobalIntsModification.CreateForSingleRowUpdate( @ParameterName, @ParameterValue ); +} +} +private partial class Cache { +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "GlobalIntsTableRetrieval", () => new Cache() ); } } +private readonly TableRetrievalQueryCache queries = new TableRetrievalQueryCache(); +private readonly Dictionary, Row> rowsByPk = new Dictionary, Row>(); +private Cache() {} +internal TableRetrievalQueryCache Queries => queries; +internal Dictionary, Row> RowsByPk => rowsByPk; +} +/// +/// Retrieves the rows from the table that match the specified conditions, ordered in a stable way. +/// +public static IEnumerable GetRows( params CommandConditions.dbo.GlobalIntsTableCondition[] conditions ) { +var parameterNameCondition = conditions.OfType().FirstOrDefault(); +var cache = Cache.Current; +var isPkQuery = parameterNameCondition != null && conditions.Count() == 1; +if( isPkQuery ) { +Row row; +if( cache.RowsByPk.TryGetValue( Tuple.Create( parameterNameCondition.Value ), out row ) ) +return new [] {row}; +} +return cache.Queries.GetResultSet( conditions.Select( i => i.CommandCondition ), commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.GlobalInts", !isPkQuery, 5, orderByClause: "ORDER BY ParameterName" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ System.Tuple.Create( i.@ParameterName ) ] = i; +} +return results; +} ); +} +public static Row GetRowMatchingPk( string parameterName, bool returnNullIfNoMatch = false ) { +return GetRows( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( parameterName ) ).PrimaryKeySingle(returnNullIfNoMatch); +} +} +} +/// +/// Contains logic that retrieves rows from the CommandRunner.DatabaseAbstraction.Table table. +/// +namespace dbo { +public static partial class @StatesTableRetrieval { +internal class BasicRow { +private readonly int @__stateId; +private readonly string @__stateName; +private readonly string @__abbreviation; +internal BasicRow( DbDataReader reader ) { +@__stateId = (int)reader.GetValue( 0 ); +@__stateName = (string)reader.GetValue( 1 ); +@__abbreviation = (string)reader.GetValue( 2 ); +} +internal int @StateId { get { return @__stateId; } } +internal string @StateName { get { return @__stateName; } } +internal string @Abbreviation { get { return @__abbreviation; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public int @StateId { get { return __basicRow.@StateId; } } +/// +/// This object will never be null. +/// +public string @StateName { get { return __basicRow.@StateName; } } +/// +/// This object will never be null. +/// +public string @Abbreviation { get { return __basicRow.@Abbreviation; } } +public override int GetHashCode() { +return @StateId.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @StateId == other.@StateId && @StateName == other.@StateName && @Abbreviation == other.@Abbreviation; +} +public Modification.dbo.@StatesModification ToModification() { +return Modification.dbo.@StatesModification.CreateForSingleRowUpdate( @StateId, @StateName, @Abbreviation ); +} +} +private partial class Cache { +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "StatesTableRetrieval", () => new Cache() ); } } +private readonly TableRetrievalQueryCache queries = new TableRetrievalQueryCache(); +private readonly Dictionary, Row> rowsByPk = new Dictionary, Row>(); +private Cache() {} +internal TableRetrievalQueryCache Queries => queries; +internal Dictionary, Row> RowsByPk => rowsByPk; +} +/// +/// Retrieves the rows from the table, ordered in a stable way. +/// +public static IEnumerable GetAllRows() { +return GetRowsMatchingConditions(); +} +/// +/// Retrieves the rows from the table that match the specified conditions, ordered in a stable way. Since the table is specified as small, you should only use this method if you cannot filter the rows in code. +/// +public static IEnumerable GetRowsMatchingConditions( params CommandConditions.dbo.StatesTableCondition[] conditions ) { +var stateIdCondition = conditions.OfType().FirstOrDefault(); +var cache = Cache.Current; +var isPkQuery = stateIdCondition != null && conditions.Count() == 1; +if( isPkQuery ) { +Row row; +if( cache.RowsByPk.TryGetValue( Tuple.Create( stateIdCondition.Value ), out row ) ) +return new [] {row}; +} +return cache.Queries.GetResultSet( conditions.Select( i => i.CommandCondition ), commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.States", !isPkQuery, 5, orderByClause: "ORDER BY StateId" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ System.Tuple.Create( i.@StateId ) ] = i; +} +return results; +} ); +} +public static Row GetRowMatchingId( int id, bool returnNullIfNoMatch = false ) { +var cache = Cache.Current; +cache.Queries.GetResultSet( new InlineDbCommandCondition[ 0 ], commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.States", true, 5, orderByClause: "ORDER BY StateId" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ System.Tuple.Create( i.@StateId ) ] = i; +} +return results; +} ); +if( !returnNullIfNoMatch ) +return cache.RowsByPk[ Tuple.Create( id ) ]; +Row row; +return cache.RowsByPk.TryGetValue( Tuple.Create( id ), out row ) ? row : null; +} +public static Dictionary ToIdDictionary( this IEnumerable rows ) { +return rows.ToDictionary( i => i.@StateId ); +} +} +} +} + +namespace Tdl.Tester.DataAccess.Modification { +namespace dbo { +public partial class @GlobalIntsModification { +/// +/// Inserts a row into the dbo.GlobalInts table. +/// +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRow( string @parameterName, int @parameterValue ) { +var mod = CreateForInsert(); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.Execute(); +} +/// +/// Inserts a row into the dbo.GlobalInts table. +/// +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRowWithoutAdditionalLogic( string @parameterName, int @parameterValue ) { +var mod = CreateForInsert(); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Updates rows in the dbo.GlobalInts table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRows( string @parameterName, int @parameterValue, CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.Execute(); +} +/// +/// Updates rows in the dbo.GlobalInts table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRowsWithoutAdditionalLogic( string @parameterName, int @parameterValue, CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRows( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +return DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var conditions = getConditionList( requiredCondition, additionalConditions ); +PostDeleteCall> postDeleteCall = null; +preDelete( conditions, ref postDeleteCall ); +var rowsDeleted = deleteRows( conditions ); +if( postDeleteCall != null ) +postDeleteCall.Execute(); +return rowsDeleted; +} ); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRowsWithoutAdditionalLogic( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var conditions = getConditionList( requiredCondition, additionalConditions ); +var rowsDeleted = deleteRows( conditions ); +return rowsDeleted; +} +private static int deleteRows( List conditions ) { +var delete = new InlineDelete( "dbo.GlobalInts", 5 ); +conditions.ForEach( condition => delete.AddCondition( condition.CommandCondition ) ); +try { +return delete.Execute( DataAccessState.Current.DatabaseConnection ); +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +static partial void preDelete( List conditions, ref PostDeleteCall> postDeleteCall ); +private ModificationType modType; +private List conditions; +private readonly DataValue @parameterNameColumnValue = new DataValue(); +/// +/// Gets or sets the value for the ParameterName column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @ParameterName { get { return @parameterNameColumnValue.Value; } set { @parameterNameColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the ParameterName has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @ParameterNameHasChanged { get { return @parameterNameColumnValue.Changed; } } +private readonly DataValue @parameterValueColumnValue = new DataValue(); +/// +/// Gets or sets the value for the ParameterValue column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public int @ParameterValue { get { return @parameterValueColumnValue.Value; } set { @parameterValueColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the ParameterValue has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @ParameterValueHasChanged { get { return @parameterValueColumnValue.Changed; } } +/// +/// Creates a modification object in insert mode, which can be used to do a piecemeal insert of a new row in the CommandRunner.DatabaseAbstraction.Table table. +/// +public static dbo.@GlobalIntsModification CreateForInsert() { +return new dbo.@GlobalIntsModification { modType = ModificationType.Insert }; +} +/// +/// Creates a modification object in update mode with the specified conditions, which can be used to do a piecemeal update of the dbo.GlobalInts table. +/// +public static dbo.@GlobalIntsModification CreateForUpdate( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = new dbo.@GlobalIntsModification { modType = ModificationType.Update, conditions = getConditionList( requiredCondition, additionalConditions ) }; +foreach( var condition in mod.conditions ) { +if( condition is CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName ) +mod.@parameterNameColumnValue.Value = ( condition as CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName ).Value; +else if( condition is CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterValue ) +mod.@parameterValueColumnValue.Value = ( condition as CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterValue ).Value; +} + +mod.markColumnValuesUnchanged(); +return mod; +} +/// +/// Creates a modification object in single-row update mode with the specified current data. All column values in this object will have HasChanged = false, despite being initialized. This object can then be used to do a piecemeal update of the dbo.GlobalInts table. +/// +public static dbo.@GlobalIntsModification CreateForSingleRowUpdate( string @parameterName, int @parameterValue ) { +var mod = new dbo.@GlobalIntsModification { modType = ModificationType.Update }; +mod.conditions = new List(); +mod.conditions.Add( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( @parameterName ) ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.markColumnValuesUnchanged(); +return mod; +} +private static List getConditionList( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var conditions = new List(); +conditions.Add( requiredCondition ); +foreach( var condition in additionalConditions ) +conditions.Add( condition ); +return conditions; +} +private @GlobalIntsModification() {} +/// +/// Sets all column values. This is useful for enforcing the number of arguments when deferred execution is needed. +/// +/// Object does not allow null. +/// Object does not allow null. +public void SetAllData( string @parameterName, int @parameterValue ) { +this.@parameterNameColumnValue.Value = @parameterName; +this.@parameterValueColumnValue.Value = @parameterValue; +} +/// +/// Executes this dbo.GlobalInts modification, persisting all changes. Executes any pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void Execute() { +DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var frozenModType = modType; +if( frozenModType == ModificationType.Insert ) +preInsert(); +else if( frozenModType == ModificationType.Update ) +preUpdate(); +executeInsertOrUpdate(); +if( frozenModType == ModificationType.Insert ) +postInsert(); +else if( frozenModType == ModificationType.Update ) +postUpdate(); +markColumnValuesUnchanged(); +} ); +} +partial void preInsert(); +partial void preUpdate(); +/// +/// Executes this dbo.GlobalInts modification, persisting all changes. Does not execute pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void ExecuteWithoutAdditionalLogic() { +executeInsertOrUpdate(); +markColumnValuesUnchanged(); +} +private void executeInsertOrUpdate() { +try { +if( modType == ModificationType.Insert ) { +var insert = new InlineInsert( "dbo.GlobalInts", false, 5 ); +addColumnModifications( insert ); +insert.Execute( DataAccessState.Current.DatabaseConnection ); +if( !@ParameterNameHasChanged ) return; +modType = ModificationType.Update; +conditions = new List(); +conditions.Add( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( @ParameterName ) ); +} +else { +var update = new InlineUpdate( "dbo.GlobalInts", 5 ); +addColumnModifications( update ); +conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) ); +update.Execute( DataAccessState.Current.DatabaseConnection ); +} +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +private void addColumnModifications( InlineDbModificationCommand cmd ) { +if( @parameterNameColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( @ParameterName, "VarChar" ) ) ); +if( @parameterValueColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( @ParameterValue, "Int" ) ) ); +} +private static void rethrowAsDataModificationExceptionIfNecessary( System.Exception e ) { +var constraintNamesToViolationErrorMessages = new Dictionary(); +populateConstraintNamesToViolationErrorMessages( constraintNamesToViolationErrorMessages ); +foreach( var pair in constraintNamesToViolationErrorMessages ) +if( e.GetBaseException().Message.ToLower().Contains( pair.Key.ToLower() ) ) throw new DataModificationException( pair.Value ); +} +static partial void populateConstraintNamesToViolationErrorMessages( Dictionary constraintNamesToViolationErrorMessages ); +partial void postInsert(); +partial void postUpdate(); +private void markColumnValuesUnchanged() { +@parameterNameColumnValue.ClearChanged(); +@parameterValueColumnValue.ClearChanged(); +} +} +} +namespace dbo { +public partial class @StatesModification { +/// +/// Inserts a row into the dbo.States table. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRow( int @stateId, string @stateName, string @abbreviation ) { +var mod = CreateForInsert(); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.Execute(); +} +/// +/// Inserts a row into the dbo.States table. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRowWithoutAdditionalLogic( int @stateId, string @stateName, string @abbreviation ) { +var mod = CreateForInsert(); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Updates rows in the dbo.States table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRows( int @stateId, string @stateName, string @abbreviation, CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.Execute(); +} +/// +/// Updates rows in the dbo.States table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRowsWithoutAdditionalLogic( int @stateId, string @stateName, string @abbreviation, CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRows( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +return DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var conditions = getConditionList( requiredCondition, additionalConditions ); +PostDeleteCall> postDeleteCall = null; +preDelete( conditions, ref postDeleteCall ); +var rowsDeleted = deleteRows( conditions ); +if( postDeleteCall != null ) +postDeleteCall.Execute(); +return rowsDeleted; +} ); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRowsWithoutAdditionalLogic( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var conditions = getConditionList( requiredCondition, additionalConditions ); +var rowsDeleted = deleteRows( conditions ); +return rowsDeleted; +} +private static int deleteRows( List conditions ) { +var delete = new InlineDelete( "dbo.States", 5 ); +conditions.ForEach( condition => delete.AddCondition( condition.CommandCondition ) ); +try { +return delete.Execute( DataAccessState.Current.DatabaseConnection ); +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +static partial void preDelete( List conditions, ref PostDeleteCall> postDeleteCall ); +private ModificationType modType; +private List conditions; +private readonly DataValue @stateIdColumnValue = new DataValue(); +/// +/// Gets or sets the value for the StateId column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public int @StateId { get { return @stateIdColumnValue.Value; } set { @stateIdColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the StateId has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @StateIdHasChanged { get { return @stateIdColumnValue.Changed; } } +private readonly DataValue @stateNameColumnValue = new DataValue(); +/// +/// Gets or sets the value for the StateName column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @StateName { get { return @stateNameColumnValue.Value; } set { @stateNameColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the StateName has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @StateNameHasChanged { get { return @stateNameColumnValue.Changed; } } +private readonly DataValue @abbreviationColumnValue = new DataValue(); +/// +/// Gets or sets the value for the Abbreviation column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @Abbreviation { get { return @abbreviationColumnValue.Value; } set { @abbreviationColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the Abbreviation has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @AbbreviationHasChanged { get { return @abbreviationColumnValue.Changed; } } +/// +/// Creates a modification object in insert mode, which can be used to do a piecemeal insert of a new row in the CommandRunner.DatabaseAbstraction.Table table. +/// +public static dbo.@StatesModification CreateForInsert() { +return new dbo.@StatesModification { modType = ModificationType.Insert }; +} +/// +/// Creates a modification object in update mode with the specified conditions, which can be used to do a piecemeal update of the dbo.States table. +/// +public static dbo.@StatesModification CreateForUpdate( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = new dbo.@StatesModification { modType = ModificationType.Update, conditions = getConditionList( requiredCondition, additionalConditions ) }; +foreach( var condition in mod.conditions ) { +if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@StateId ) +mod.@stateIdColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@StateId ).Value; +else if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@StateName ) +mod.@stateNameColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@StateName ).Value; +else if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@Abbreviation ) +mod.@abbreviationColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@Abbreviation ).Value; +} + +mod.markColumnValuesUnchanged(); +return mod; +} +/// +/// Creates a modification object in single-row update mode with the specified current data. All column values in this object will have HasChanged = false, despite being initialized. This object can then be used to do a piecemeal update of the dbo.States table. +/// +public static dbo.@StatesModification CreateForSingleRowUpdate( int @stateId, string @stateName, string @abbreviation ) { +var mod = new dbo.@StatesModification { modType = ModificationType.Update }; +mod.conditions = new List(); +mod.conditions.Add( new CommandConditions.dbo.@StatesTableEqualityConditions.@StateId( @stateId ) ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.markColumnValuesUnchanged(); +return mod; +} +private static List getConditionList( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var conditions = new List(); +conditions.Add( requiredCondition ); +foreach( var condition in additionalConditions ) +conditions.Add( condition ); +return conditions; +} +private @StatesModification() {} +/// +/// Sets all column values. This is useful for enforcing the number of arguments when deferred execution is needed. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public void SetAllData( int @stateId, string @stateName, string @abbreviation ) { +this.@stateIdColumnValue.Value = @stateId; +this.@stateNameColumnValue.Value = @stateName; +this.@abbreviationColumnValue.Value = @abbreviation; +} +/// +/// Executes this dbo.States modification, persisting all changes. Executes any pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void Execute() { +DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var frozenModType = modType; +if( frozenModType == ModificationType.Insert ) +preInsert(); +else if( frozenModType == ModificationType.Update ) +preUpdate(); +executeInsertOrUpdate(); +if( frozenModType == ModificationType.Insert ) +postInsert(); +else if( frozenModType == ModificationType.Update ) +postUpdate(); +markColumnValuesUnchanged(); +} ); +} +partial void preInsert(); +partial void preUpdate(); +/// +/// Executes this dbo.States modification, persisting all changes. Does not execute pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void ExecuteWithoutAdditionalLogic() { +executeInsertOrUpdate(); +markColumnValuesUnchanged(); +} +private void executeInsertOrUpdate() { +try { +if( modType == ModificationType.Insert ) { +var insert = new InlineInsert( "dbo.States", false, 5 ); +addColumnModifications( insert ); +insert.Execute( DataAccessState.Current.DatabaseConnection ); +if( !@StateIdHasChanged ) return; +modType = ModificationType.Update; +conditions = new List(); +conditions.Add( new CommandConditions.dbo.@StatesTableEqualityConditions.@StateId( @StateId ) ); +} +else { +var update = new InlineUpdate( "dbo.States", 5 ); +addColumnModifications( update ); +conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) ); +update.Execute( DataAccessState.Current.DatabaseConnection ); +} +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +private void addColumnModifications( InlineDbModificationCommand cmd ) { +if( @stateIdColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "StateId", new DbParameterValue( @StateId, "Int" ) ) ); +if( @stateNameColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "StateName", new DbParameterValue( @StateName, "NVarChar" ) ) ); +if( @abbreviationColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( @Abbreviation, "NVarChar" ) ) ); +} +private static void rethrowAsDataModificationExceptionIfNecessary( System.Exception e ) { +var constraintNamesToViolationErrorMessages = new Dictionary(); +populateConstraintNamesToViolationErrorMessages( constraintNamesToViolationErrorMessages ); +foreach( var pair in constraintNamesToViolationErrorMessages ) +if( e.GetBaseException().Message.ToLower().Contains( pair.Key.ToLower() ) ) throw new DataModificationException( pair.Value ); +} +static partial void populateConstraintNamesToViolationErrorMessages( Dictionary constraintNamesToViolationErrorMessages ); +partial void postInsert(); +partial void postUpdate(); +private void markColumnValuesUnchanged() { +@stateIdColumnValue.ClearChanged(); +@stateNameColumnValue.ClearChanged(); +@abbreviationColumnValue.ClearChanged(); +} +} +} +} + +namespace Tdl.Tester.DataAccess.Retrieval { +/// +/// This object holds the values returned from a PrimarySequence query. +/// +public static partial class PrimarySequenceRetrieval { +internal class BasicRow { +private readonly int @__id; +internal BasicRow( DbDataReader reader ) { +@__id = (int)reader.GetValue( 0 ); +} +internal int @Id { get { return @__id; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public int @Id { get { return __basicRow.@Id; } } +public override int GetHashCode() { +return @Id.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @Id == other.@Id; +} +} +private partial class Cache { +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "PrimarySequenceQueryRetrieval", () => new Cache() ); } } +private readonly ParameterlessQueryCache rowsNextQuery = new ParameterlessQueryCache(); +private Cache() {} +internal ParameterlessQueryCache RowsNextQuery { get { return rowsNextQuery; } } +} +private const string selectFromClause = @"SELECT NEXT VALUE FOR PrimarySequence as Id "; +/// +/// Queries the database and returns the full results collection immediately. +/// +public static IEnumerable GetRowsNext( ) { +return Cache.Current.RowsNextQuery.GetResultSet( () => { +var cmd = DataAccessState.Current.DatabaseConnection.DatabaseInfo.CreateCommand(5); +cmd.CommandText = selectFromClause +;var results = new List(); +DataAccessState.Current.DatabaseConnection.ExecuteReaderCommand( cmd, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) +updateSingleRowCaches( i ); +return results; +} ); +} +static partial void updateSingleRowCaches( Row row ); +} +} + diff --git a/TdlTester/app.config b/TdlTester/app.config new file mode 100644 index 0000000..01497da --- /dev/null +++ b/TdlTester/app.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/TestTdlDml/App.config b/TestTdlDml/App.config new file mode 100644 index 0000000..966cc51 --- /dev/null +++ b/TestTdlDml/App.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/TestTdlDml/Program.cs b/TestTdlDml/Program.cs new file mode 100644 index 0000000..cfa17a4 --- /dev/null +++ b/TestTdlDml/Program.cs @@ -0,0 +1,67 @@ +using System; +using System.Diagnostics; +using System.Linq; +using Tdl.TestGeneration.DataAccess.CommandConditions.dbo; +using Tdl.TestGeneration.DataAccess.Modification.dbo; +using Tdl.TestGeneration.DataAccess.TableRetrieval.dbo; +using TypedDataLayer; + +namespace Tdl.TestDml { + class Program { + static void Main() { + assertTransactionsRollbackOnException(); + assertUpdatesAffectOnlySpecifiedRows(); + assertCachePkLookupsWork(); + } + + private static void assertTransactionsRollbackOnException() { + try { + Database.ExecuteInDbConnectionWithTransaction( + () => { + assertStateHasName( "NY", "New York" ); + var stateMod = StatesModification.CreateForUpdate( new StatesTableEqualityConditions.Abbreviation( "NY" ) ); + stateMod.StateName = "ShouldBeRolledBack"; + stateMod.Execute(); + assertStateHasName( "NY", "ShouldBeRolledBack" ); + throw new ApplicationException( "Simulated unexpected error thrown by developer code inside a transaction." ); + } ); + } + catch { } + + Database.ExecuteInDbConnectionWithTransaction( () => { assertStateHasName( "NY", "New York" ); } ); + } + + private static void assertUpdatesAffectOnlySpecifiedRows() { + Database.ExecuteInDbConnection( + () => { + assertStateHasName( "NY", "New York" ); + assertStateHasName( "AZ", "Arizona" ); + + var stateMod = StatesModification.CreateForUpdate( new StatesTableEqualityConditions.Abbreviation( "NY" ) ); + stateMod.StateName = "Modified"; + stateMod.Execute(); + + assertStateHasName( "NY", "Modified" ); + assertStateHasName( "AZ", "Arizona" ); + + stateMod.StateName = "New York"; + stateMod.Execute(); + assertStateHasName( "NY", "New York" ); + } ); + } + + private static void assertStateHasName( string stateAbbreviation, string stateName ) { + var state = StatesTableRetrieval.GetRowsMatchingConditions( new StatesTableEqualityConditions.Abbreviation( stateAbbreviation ) ).Single(); + Debug.Assert( stateName == state.StateName ); + } + + private static void assertCachePkLookupsWork() { + Database.ExecuteInDbConnectionWithTransactionWithCaching( + () => { + var ny = StatesTableRetrieval.GetRowMatchingId( 4000 ); + var nyCached = StatesTableRetrieval.GetRowMatchingId( 4000 ); + // GMS NOTE: Not sure what we can really assert here - we can't tell if it really went to the database. Pretty much had to debug it. + } ); + } + } +} \ No newline at end of file diff --git a/TestTdlDml/Properties/AssemblyInfo.cs b/TestTdlDml/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..696210d --- /dev/null +++ b/TestTdlDml/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "TestTdlDml" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "" )] +[assembly: AssemblyProduct( "TestTdlDml" )] +[assembly: AssemblyCopyright( "Copyright © 2020" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "52f1219a-7ee4-40af-b12a-2a4e01e750c4" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/TestTdlDml/TestTdlDml.csproj b/TestTdlDml/TestTdlDml.csproj new file mode 100644 index 0000000..29acd8c --- /dev/null +++ b/TestTdlDml/TestTdlDml.csproj @@ -0,0 +1,83 @@ + + + + + Debug + AnyCPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4} + Exe + Tdl.TestDml + Tdl.TestDml + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + + + {3718cc44-0f9a-46b2-a56f-7e56032db725} + TestTdlGeneration + + + {86a9c472-70ea-4dd1-b36e-5276c754e720} + TypedDataLayer + + + + \ No newline at end of file diff --git a/TestTdlGeneration/App.config b/TestTdlGeneration/App.config new file mode 100644 index 0000000..b92571a --- /dev/null +++ b/TestTdlGeneration/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TestTdlGeneration/CreateTestDb.sql b/TestTdlGeneration/CreateTestDb.sql new file mode 100644 index 0000000..a273997 --- /dev/null +++ b/TestTdlGeneration/CreateTestDb.sql @@ -0,0 +1,38 @@ +CREATE DATABASE TdlTest +GO + +USE TdlTest +GO +ALTER DATABASE TdlTest SET PAGE_VERIFY CHECKSUM +ALTER DATABASE TdlTest SET AUTO_CREATE_STATISTICS ON (INCREMENTAL = ON) +ALTER DATABASE TdlTest SET AUTO_UPDATE_STATISTICS_ASYNC ON +ALTER DATABASE TdlTest SET ALLOW_SNAPSHOT_ISOLATION ON +ALTER DATABASE TdlTest SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE +GO + +CREATE TABLE GlobalInts( + ParameterName varchar( 50 ) + NOT NULL + CONSTRAINT GlobalIntsPk PRIMARY KEY, + ParameterValue int + NOT NULL +) + +INSERT INTO GlobalInts VALUES( 'LineMarker', 0 ) +GO + +CREATE SEQUENCE PrimarySequence AS int start with 1; +GO + +CREATE TABLE States ( + StateId int NOT NULL CONSTRAINT pkStates PRIMARY KEY, + StateName nvarchar( 50 ) NOT NULL CONSTRAINT uniqueStateName UNIQUE, + Abbreviation nvarchar( 2 ) NOT NULL CONSTRAINT uniqueStateAbbr UNIQUE +) +GO +INSERT INTO States VALUES( 1, 'Alabama', 'AL' ); +INSERT INTO States VALUES( 2, 'Alaska', 'AK' ); +INSERT INTO States VALUES( 3, 'Arizona', 'AZ' ); +INSERT INTO States VALUES( 4, 'Arkansas', 'AR' ); +INSERT INTO States VALUES( 4000, 'New York', 'NY' ); +GO \ No newline at end of file diff --git a/TestTdlGeneration/Program.cs b/TestTdlGeneration/Program.cs new file mode 100644 index 0000000..ae0fa73 --- /dev/null +++ b/TestTdlGeneration/Program.cs @@ -0,0 +1,20 @@ +using System.Diagnostics; + +namespace Tdl.TestGeneration { + class Program { + static void Main( string[] args ) { + Debug.WriteLine( "Hello World!" ); + //var workingDirectory = ConfigurationManager.AppSettings[ "token" ]; + CommandRunner.Program.LoadConfigAndRunUpdateAllDependentLogic( @"C:\GitHub\TypedDataLayer\TestTdlGeneration", true ); + } + + /* + Where to try runtime retrieval of "keys" or columns with IsKey=true? + What is TablesUsingRowVersionedDataCaching? Is that revision history or something else? Can we axe it? + + Why does backspace no longer delete the entire line regardless of whitespace? + Why does debug work when I start VS but not after? + Why does it always step in/pretend I have a backpoint set on the first line? + */ + } +} diff --git a/TestTdlGeneration/Properties/AssemblyInfo.cs b/TestTdlGeneration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..195c48a --- /dev/null +++ b/TestTdlGeneration/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "TestTdlGeneration" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "" )] +[assembly: AssemblyProduct( "TestTdlGeneration" )] +[assembly: AssemblyCopyright( "Copyright © 2020" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "3718cc44-0f9a-46b2-a56f-7e56032db725" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/TestTdlGeneration/Readme.txt b/TestTdlGeneration/Readme.txt new file mode 100644 index 0000000..4502abf --- /dev/null +++ b/TestTdlGeneration/Readme.txt @@ -0,0 +1,5 @@ +This test project is not central to the design or function of the TDL tool. + +This test project should not need to build in order to use/deploy/modify TDL. + +This test project should not fail to build just because the machine does not have the/a test database. The dev should not be obligated to create a test database. \ No newline at end of file diff --git a/TestTdlGeneration/TestTdlGeneration.csproj b/TestTdlGeneration/TestTdlGeneration.csproj new file mode 100644 index 0000000..4efe68f --- /dev/null +++ b/TestTdlGeneration/TestTdlGeneration.csproj @@ -0,0 +1,89 @@ + + + + + Debug + AnyCPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725} + Exe + Tdl.TestGeneration + Tdl.TestGeneration + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + + + + + + + + + {a81039df-def4-40b8-a770-6dd3450e0961} + CommandRunner + + + {86a9c472-70ea-4dd1-b36e-5276c754e720} + TypedDataLayer + + + + \ No newline at end of file diff --git a/TestTdlGeneration/TypedDataLayer/Configuration.xml b/TestTdlGeneration/TypedDataLayer/Configuration.xml new file mode 100644 index 0000000..88d1925 --- /dev/null +++ b/TestTdlGeneration/TypedDataLayer/Configuration.xml @@ -0,0 +1,25 @@ + + +Tdl.TestGeneration + + data source=(local);Initial Catalog=TdlTest;Integrated Security=SSPI; + + + 5 + + + + +
dbo.States
+ + + + SELECT NEXT VALUE FOR PrimarySequence as Id + + + + + +
+
\ No newline at end of file diff --git a/TestTdlGeneration/TypedDataLayer/GeneratedCode/TypedDataLayer.cs b/TestTdlGeneration/TypedDataLayer/GeneratedCode/TypedDataLayer.cs new file mode 100644 index 0000000..78cf5c8 --- /dev/null +++ b/TestTdlGeneration/TypedDataLayer/GeneratedCode/TypedDataLayer.cs @@ -0,0 +1,1225 @@ +using System; +using System.Globalization; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Diagnostics; +using System.Linq; +using TypedDataLayer; +using TypedDataLayer.Tools; +using TypedDataLayer.Exceptions; +using TypedDataLayer.DatabaseSpecification; +using TypedDataLayer.DatabaseSpecification.Databases; +using TypedDataLayer.DataAccess; +using TypedDataLayer.DataAccess.StandardModification; +using TypedDataLayer.DataAccess.RetrievalCaching; +using TypedDataLayer.DataAccess.CommandWriting; +using TypedDataLayer.DataAccess.CommandWriting.InlineConditionAbstraction; +using TypedDataLayer.DataAccess.CommandWriting.InlineConditionAbstraction.Conditions; +using TypedDataLayer.DataAccess.CommandWriting.Commands; +using TypedDataLayer.Containers; +using TypedDataLayer.Collections; + +namespace Tdl.TestGeneration.DataAccess { +public static class Configuration { +public const int CommandTimeoutSeconds = 5; +} +} + +namespace Tdl.TestGeneration.DataAccess.TableConstants { +namespace dbo { +/// +/// This object represents the constants of the CommandRunner.DatabaseAbstraction.Table table. +/// +public class @GlobalIntsTable { +/// +/// The name of this table. +/// +public const string Name = "CommandRunner.DatabaseAbstraction.Table"; +/// +/// Contains schema information about this column. +/// +public class @ParameterNameColumn { +/// +/// The name of this column. +/// +public const string Name = "ParameterName"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 50; +} +/// +/// Contains schema information about this column. +/// +public class @ParameterValueColumn { +/// +/// The name of this column. +/// +public const string Name = "ParameterValue"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 4; +} +} +} +namespace dbo { +/// +/// This object represents the constants of the CommandRunner.DatabaseAbstraction.Table table. +/// +public class @StatesTable { +/// +/// The name of this table. +/// +public const string Name = "CommandRunner.DatabaseAbstraction.Table"; +/// +/// Contains schema information about this column. +/// +public class @StateIdColumn { +/// +/// The name of this column. +/// +public const string Name = "StateId"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 4; +} +/// +/// Contains schema information about this column. +/// +public class @StateNameColumn { +/// +/// The name of this column. +/// +public const string Name = "StateName"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 50; +} +/// +/// Contains schema information about this column. +/// +public class @AbbreviationColumn { +/// +/// The name of this column. +/// +public const string Name = "Abbreviation"; +/// +/// The size of this column. For varchars, this is the length of the biggest string that can be stored in this column. +/// +public const int Size = 2; +} +} +} +} + +namespace Tdl.TestGeneration.DataAccess.RowConstants { +namespace dbo { +/// +/// Provides constants copied from the dbo.States table. +/// +public class StatesRows { +/// +/// Constant generated from row in database table. +/// +public const int @Ak = 2; +/// +/// Constant generated from row in database table. +/// +public const int @Al = 1; +/// +/// Constant generated from row in database table. +/// +public const int @Ar = 4; +/// +/// Constant generated from row in database table. +/// +public const int @Az = 3; +/// +/// Constant generated from row in database table. +/// +public const int @Ny = 4000; +private static readonly OneToOneMap valuesAndNames = new OneToOneMap(); +static StatesRows() { +valuesAndNames.Add( (int)(2), "AK" ); +valuesAndNames.Add( (int)(1), "AL" ); +valuesAndNames.Add( (int)(4), "AR" ); +valuesAndNames.Add( (int)(3), "AZ" ); +valuesAndNames.Add( (int)(4000), "NY" ); +} +/// +/// Returns the name of the constant given the constant's value. +/// +public static string GetNameFromValue( int constantValue ) { +return valuesAndNames.GetRightFromLeft( constantValue ); +} +/// +/// Returns the value of the constant given the constant's name. +/// +public static int GetValueFromName( string constantName ) { +return valuesAndNames.GetLeftFromRight( constantName ); +} +} +} +} + +namespace Tdl.TestGeneration.DataAccess.CommandConditions { +namespace dbo { +public interface GlobalIntsTableCondition: TableCondition {} +public static class @GlobalIntsTableEqualityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( value, "VarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( int value ) { +this.value = value; +} +internal int Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( value, "Int" ) ) ); } } +} +} +public static class @GlobalIntsTableInequalityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @ParameterName( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( value, "VarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly InequalityCondition.Operator op; +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @ParameterValue( InequalityCondition.Operator op, int value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( value, "Int" ) ) ); } } +} +} +public static class @GlobalIntsTableInConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "ParameterName", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "ParameterValue", subQuery ); } } +} +} +public static class @GlobalIntsTableLikeConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterName: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterName( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "ParameterName", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @ParameterValue: CommandConditions.dbo.GlobalIntsTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @ParameterValue( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "ParameterValue", value ); } } +} +} +} +namespace dbo { +public interface StatesTableCondition: TableCondition {} +public static class @StatesTableEqualityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( int value ) { +this.value = value; +} +internal int Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "StateId", new DbParameterValue( value, "Int" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "StateName", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( string value ) { +this.value = value; +} +internal string Value { get { return value; } } +InlineDbCommandCondition TableCondition.CommandCondition { get { return new EqualityCondition( new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +} +public static class @StatesTableInequalityConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly int value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @StateId( InequalityCondition.Operator op, int value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "StateId", new DbParameterValue( value, "Int" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @StateName( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "StateName", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly InequalityCondition.Operator op; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. Expression will read 'valueInDatabase op yourValue'. So new InequalityCondition( Operator.GreaterThan, value ) will turn into 'columnName > @value'. +/// +public @Abbreviation( InequalityCondition.Operator op, string value ) { +this.op = op; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InequalityCondition( op, new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( value, "NVarChar" ) ) ); } } +} +} +public static class @StatesTableInConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "StateId", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "StateName", subQuery ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly string subQuery; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( string subQuery ) { +this.subQuery = subQuery; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new InCondition( "Abbreviation", subQuery ); } } +} +} +public static class @StatesTableLikeConditions { +/// +/// A condition that narrows the scope of a command. +/// +public class @StateId: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateId( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "StateId", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @StateName: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @StateName( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "StateName", value ); } } +} +/// +/// A condition that narrows the scope of a command. +/// +public class @Abbreviation: CommandConditions.dbo.StatesTableCondition { +private readonly LikeCondition.Behavior behavior; +private readonly string value; +/// +/// Creates a condition to narrow the scope of a command. +/// +public @Abbreviation( LikeCondition.Behavior behavior, string value ) { +this.behavior = behavior; +this.value = value; +} +InlineDbCommandCondition TableCondition.CommandCondition { get { return new LikeCondition( behavior, "Abbreviation", value ); } } +} +} +} +} + +namespace Tdl.TestGeneration.DataAccess.TableRetrieval { +/// +/// Contains logic that retrieves rows from the CommandRunner.DatabaseAbstraction.Table table. +/// +namespace dbo { +public static partial class @GlobalIntsTableRetrieval { +internal class BasicRow { +private readonly string @__parameterName; +private readonly int @__parameterValue; +internal BasicRow( DbDataReader reader ) { +@__parameterName = (string)reader.GetValue( 0 ); +@__parameterValue = (int)reader.GetValue( 1 ); +} +internal string @ParameterName { get { return @__parameterName; } } +internal int @ParameterValue { get { return @__parameterValue; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public string @ParameterName { get { return __basicRow.@ParameterName; } } +/// +/// This object will never be null. +/// +public int @ParameterValue { get { return __basicRow.@ParameterValue; } } +public override int GetHashCode() { +return @ParameterName.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @ParameterName == other.@ParameterName && @ParameterValue == other.@ParameterValue; +} +public Modification.dbo.@GlobalIntsModification ToModification() { +return Modification.dbo.@GlobalIntsModification.CreateForSingleRowUpdate( @ParameterName, @ParameterValue ); +} +} +private partial class Cache { +internal struct Key { +internal string ParameterName; +} +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "GlobalIntsTableRetrieval", () => new Cache() ); } } +private readonly TableRetrievalQueryCache queries = new TableRetrievalQueryCache(); +private readonly Dictionary rowsByPk = new Dictionary(); +private Cache() {} +internal TableRetrievalQueryCache Queries => queries; +internal Dictionary RowsByPk => rowsByPk; +} +/// +/// Retrieves the rows from the table that match the specified conditions, ordered in a stable way. +/// +public static IEnumerable GetRows( params CommandConditions.dbo.GlobalIntsTableCondition[] conditions ) { +var parameterNameCondition = conditions.OfType().FirstOrDefault(); +var cache = Cache.Current; +var isPkQuery = parameterNameCondition != null && conditions.Count() == 1; +if( isPkQuery ) { +Row row; +if( cache.RowsByPk.TryGetValue( new Cache.Key {ParameterName = parameterNameCondition.Value}, out row ) ) +return new [] {row}; +} +return cache.Queries.GetResultSet( conditions.Select( i => i.CommandCondition ), commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.GlobalInts", !isPkQuery, 5, orderByClause: "ORDER BY ParameterName" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ new Cache.Key {ParameterName = i.ParameterName} ] = i; +} +return results; +} ); +} +public static Row GetRowMatchingPk( string parameterName, bool returnNullIfNoMatch = false ) { +return GetRows( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( parameterName ) ).PrimaryKeySingle(returnNullIfNoMatch); +} +} +} +/// +/// Contains logic that retrieves rows from the CommandRunner.DatabaseAbstraction.Table table. +/// +namespace dbo { +public static partial class @StatesTableRetrieval { +internal class BasicRow { +private readonly int @__stateId; +private readonly string @__stateName; +private readonly string @__abbreviation; +internal BasicRow( DbDataReader reader ) { +@__stateId = (int)reader.GetValue( 0 ); +@__stateName = (string)reader.GetValue( 1 ); +@__abbreviation = (string)reader.GetValue( 2 ); +} +internal int @StateId { get { return @__stateId; } } +internal string @StateName { get { return @__stateName; } } +internal string @Abbreviation { get { return @__abbreviation; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public int @StateId { get { return __basicRow.@StateId; } } +/// +/// This object will never be null. +/// +public string @StateName { get { return __basicRow.@StateName; } } +/// +/// This object will never be null. +/// +public string @Abbreviation { get { return __basicRow.@Abbreviation; } } +public override int GetHashCode() { +return @StateId.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @StateId == other.@StateId && @StateName == other.@StateName && @Abbreviation == other.@Abbreviation; +} +public Modification.dbo.@StatesModification ToModification() { +return Modification.dbo.@StatesModification.CreateForSingleRowUpdate( @StateId, @StateName, @Abbreviation ); +} +} +private partial class Cache { +internal struct Key { +internal int StateId; +} +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "StatesTableRetrieval", () => new Cache() ); } } +private readonly TableRetrievalQueryCache queries = new TableRetrievalQueryCache(); +private readonly Dictionary rowsByPk = new Dictionary(); +private Cache() {} +internal TableRetrievalQueryCache Queries => queries; +internal Dictionary RowsByPk => rowsByPk; +} +/// +/// Retrieves the rows from the table, ordered in a stable way. +/// +public static IEnumerable GetAllRows() { +return GetRowsMatchingConditions(); +} +/// +/// Retrieves the rows from the table that match the specified conditions, ordered in a stable way. Since the table is specified as small, you should only use this method if you cannot filter the rows in code. +/// +public static IEnumerable GetRowsMatchingConditions( params CommandConditions.dbo.StatesTableCondition[] conditions ) { +var stateIdCondition = conditions.OfType().FirstOrDefault(); +var cache = Cache.Current; +var isPkQuery = stateIdCondition != null && conditions.Count() == 1; +if( isPkQuery ) { +Row row; +if( cache.RowsByPk.TryGetValue( new Cache.Key {StateId = stateIdCondition.Value}, out row ) ) +return new [] {row}; +} +return cache.Queries.GetResultSet( conditions.Select( i => i.CommandCondition ), commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.States", !isPkQuery, 5, orderByClause: "ORDER BY StateId" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ new Cache.Key {StateId = i.StateId} ] = i; +} +return results; +} ); +} +public static Row GetRowMatchingId( int id, bool returnNullIfNoMatch = false ) { +var cache = Cache.Current; +cache.Queries.GetResultSet( new InlineDbCommandCondition[ 0 ], commandConditions => { +var command = new InlineSelect( new[] { "*" }, "FROM dbo.States", true, 5, orderByClause: "ORDER BY StateId" ); +foreach( var i in commandConditions ) command.AddCondition( i ); +var results = new List(); +command.Execute( DataAccessState.Current.DatabaseConnection, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) { +cache.RowsByPk[ new Cache.Key {StateId = i.StateId} ] = i; +} +return results; +} ); +if( !returnNullIfNoMatch ) +return cache.RowsByPk[ new Cache.Key {StateId = id} ]; +Row row; +return cache.RowsByPk.TryGetValue( new Cache.Key {StateId = id}, out row ) ? row : null; +} +public static Dictionary ToIdDictionary( this IEnumerable rows ) { +return rows.ToDictionary( i => i.@StateId ); +} +} +} +} + +namespace Tdl.TestGeneration.DataAccess.Modification { +namespace dbo { +public partial class @GlobalIntsModification { +/// +/// Inserts a row into the dbo.GlobalInts table. +/// +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRow( string @parameterName, int @parameterValue ) { +var mod = CreateForInsert(); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.Execute(); +} +/// +/// Inserts a row into the dbo.GlobalInts table. +/// +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRowWithoutAdditionalLogic( string @parameterName, int @parameterValue ) { +var mod = CreateForInsert(); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Updates rows in the dbo.GlobalInts table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRows( string @parameterName, int @parameterValue, CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.Execute(); +} +/// +/// Updates rows in the dbo.GlobalInts table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRowsWithoutAdditionalLogic( string @parameterName, int @parameterValue, CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRows( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +return DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var conditions = getConditionList( requiredCondition, additionalConditions ); +PostDeleteCall> postDeleteCall = null; +preDelete( conditions, ref postDeleteCall ); +var rowsDeleted = deleteRows( conditions ); +if( postDeleteCall != null ) +postDeleteCall.Execute(); +return rowsDeleted; +} ); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRowsWithoutAdditionalLogic( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var conditions = getConditionList( requiredCondition, additionalConditions ); +var rowsDeleted = deleteRows( conditions ); +return rowsDeleted; +} +private static int deleteRows( List conditions ) { +var delete = new InlineDelete( "dbo.GlobalInts", 5 ); +conditions.ForEach( condition => delete.AddCondition( condition.CommandCondition ) ); +try { +return delete.Execute( DataAccessState.Current.DatabaseConnection ); +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +static partial void preDelete( List conditions, ref PostDeleteCall> postDeleteCall ); +private ModificationType modType; +private List conditions; +private readonly DataValue @parameterNameColumnValue = new DataValue(); +/// +/// Gets or sets the value for the ParameterName column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @ParameterName { get { return @parameterNameColumnValue.Value; } set { @parameterNameColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the ParameterName has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @ParameterNameHasChanged { get { return @parameterNameColumnValue.Changed; } } +private readonly DataValue @parameterValueColumnValue = new DataValue(); +/// +/// Gets or sets the value for the ParameterValue column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public int @ParameterValue { get { return @parameterValueColumnValue.Value; } set { @parameterValueColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the ParameterValue has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @ParameterValueHasChanged { get { return @parameterValueColumnValue.Changed; } } +/// +/// Creates a modification object in insert mode, which can be used to do a piecemeal insert of a new row in the CommandRunner.DatabaseAbstraction.Table table. +/// +public static dbo.@GlobalIntsModification CreateForInsert() { +return new dbo.@GlobalIntsModification { modType = ModificationType.Insert }; +} +/// +/// Creates a modification object in update mode with the specified conditions, which can be used to do a piecemeal update of the dbo.GlobalInts table. +/// +public static dbo.@GlobalIntsModification CreateForUpdate( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var mod = new dbo.@GlobalIntsModification { modType = ModificationType.Update, conditions = getConditionList( requiredCondition, additionalConditions ) }; +foreach( var condition in mod.conditions ) { +if( condition is CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName ) +mod.@parameterNameColumnValue.Value = ( condition as CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName ).Value; +else if( condition is CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterValue ) +mod.@parameterValueColumnValue.Value = ( condition as CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterValue ).Value; +} + +mod.markColumnValuesUnchanged(); +return mod; +} +/// +/// Creates a modification object in single-row update mode with the specified current data. All column values in this object will have HasChanged = false, despite being initialized. This object can then be used to do a piecemeal update of the dbo.GlobalInts table. +/// +public static dbo.@GlobalIntsModification CreateForSingleRowUpdate( string @parameterName, int @parameterValue ) { +var mod = new dbo.@GlobalIntsModification { modType = ModificationType.Update }; +mod.conditions = new List(); +mod.conditions.Add( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( @parameterName ) ); +mod.@parameterNameColumnValue.Value = @parameterName; +mod.@parameterValueColumnValue.Value = @parameterValue; +mod.markColumnValuesUnchanged(); +return mod; +} +private static List getConditionList( CommandConditions.dbo.GlobalIntsTableCondition requiredCondition, params CommandConditions.dbo.GlobalIntsTableCondition[] additionalConditions ) { +var conditions = new List(); +conditions.Add( requiredCondition ); +foreach( var condition in additionalConditions ) +conditions.Add( condition ); +return conditions; +} +private @GlobalIntsModification() {} +/// +/// Sets all column values. This is useful for enforcing the number of arguments when deferred execution is needed. +/// +/// Object does not allow null. +/// Object does not allow null. +public void SetAllData( string @parameterName, int @parameterValue ) { +this.@parameterNameColumnValue.Value = @parameterName; +this.@parameterValueColumnValue.Value = @parameterValue; +} +/// +/// Executes this dbo.GlobalInts modification, persisting all changes. Executes any pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void Execute() { +DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var frozenModType = modType; +if( frozenModType == ModificationType.Insert ) +preInsert(); +else if( frozenModType == ModificationType.Update ) +preUpdate(); +executeInsertOrUpdate(); +if( frozenModType == ModificationType.Insert ) +postInsert(); +else if( frozenModType == ModificationType.Update ) +postUpdate(); +markColumnValuesUnchanged(); +} ); +} +partial void preInsert(); +partial void preUpdate(); +/// +/// Executes this dbo.GlobalInts modification, persisting all changes. Does not execute pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void ExecuteWithoutAdditionalLogic() { +executeInsertOrUpdate(); +markColumnValuesUnchanged(); +} +private void executeInsertOrUpdate() { +try { +if( modType == ModificationType.Insert ) { +var insert = new InlineInsert( "dbo.GlobalInts", false, 5 ); +addColumnModifications( insert ); +insert.Execute( DataAccessState.Current.DatabaseConnection ); +if( !@ParameterNameHasChanged ) return; +modType = ModificationType.Update; +conditions = new List(); +conditions.Add( new CommandConditions.dbo.@GlobalIntsTableEqualityConditions.@ParameterName( @ParameterName ) ); +} +else { +var update = new InlineUpdate( "dbo.GlobalInts", 5 ); +addColumnModifications( update ); +conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) ); +update.Execute( DataAccessState.Current.DatabaseConnection ); +} +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +private void addColumnModifications( InlineDbModificationCommand cmd ) { +if( @parameterNameColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "ParameterName", new DbParameterValue( @ParameterName, "VarChar" ) ) ); +if( @parameterValueColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "ParameterValue", new DbParameterValue( @ParameterValue, "Int" ) ) ); +} +private static void rethrowAsDataModificationExceptionIfNecessary( System.Exception e ) { +var constraintNamesToViolationErrorMessages = new Dictionary(); +populateConstraintNamesToViolationErrorMessages( constraintNamesToViolationErrorMessages ); +foreach( var pair in constraintNamesToViolationErrorMessages ) +if( e.GetBaseException().Message.ToLower().Contains( pair.Key.ToLower() ) ) throw new DataModificationException( pair.Value ); +} +static partial void populateConstraintNamesToViolationErrorMessages( Dictionary constraintNamesToViolationErrorMessages ); +partial void postInsert(); +partial void postUpdate(); +private void markColumnValuesUnchanged() { +@parameterNameColumnValue.ClearChanged(); +@parameterValueColumnValue.ClearChanged(); +} +} +} +namespace dbo { +public partial class @StatesModification { +/// +/// Inserts a row into the dbo.States table. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRow( int @stateId, string @stateName, string @abbreviation ) { +var mod = CreateForInsert(); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.Execute(); +} +/// +/// Inserts a row into the dbo.States table. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public static void InsertRowWithoutAdditionalLogic( int @stateId, string @stateName, string @abbreviation ) { +var mod = CreateForInsert(); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Updates rows in the dbo.States table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRows( int @stateId, string @stateName, string @abbreviation, CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.Execute(); +} +/// +/// Updates rows in the dbo.States table that match the specified conditions with the specified data. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +/// A condition. +/// Additional conditions. +public static void UpdateRowsWithoutAdditionalLogic( int @stateId, string @stateName, string @abbreviation, CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = CreateForUpdate( requiredCondition, additionalConditions ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.ExecuteWithoutAdditionalLogic(); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRows( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +return DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var conditions = getConditionList( requiredCondition, additionalConditions ); +PostDeleteCall> postDeleteCall = null; +preDelete( conditions, ref postDeleteCall ); +var rowsDeleted = deleteRows( conditions ); +if( postDeleteCall != null ) +postDeleteCall.Execute(); +return rowsDeleted; +} ); +} +/// +/// Deletes the rows that match the specified conditions and returns the number of rows deleted.WARNING: After calling this method, delete referenced rows in other tables that are no longer needed. +/// +public static int DeleteRowsWithoutAdditionalLogic( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var conditions = getConditionList( requiredCondition, additionalConditions ); +var rowsDeleted = deleteRows( conditions ); +return rowsDeleted; +} +private static int deleteRows( List conditions ) { +var delete = new InlineDelete( "dbo.States", 5 ); +conditions.ForEach( condition => delete.AddCondition( condition.CommandCondition ) ); +try { +return delete.Execute( DataAccessState.Current.DatabaseConnection ); +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +static partial void preDelete( List conditions, ref PostDeleteCall> postDeleteCall ); +private ModificationType modType; +private List conditions; +private readonly DataValue @stateIdColumnValue = new DataValue(); +/// +/// Gets or sets the value for the StateId column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public int @StateId { get { return @stateIdColumnValue.Value; } set { @stateIdColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the StateId has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @StateIdHasChanged { get { return @stateIdColumnValue.Changed; } } +private readonly DataValue @stateNameColumnValue = new DataValue(); +/// +/// Gets or sets the value for the StateName column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @StateName { get { return @stateNameColumnValue.Value; } set { @stateNameColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the StateName has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @StateNameHasChanged { get { return @stateNameColumnValue.Changed; } } +private readonly DataValue @abbreviationColumnValue = new DataValue(); +/// +/// Gets or sets the value for the Abbreviation column. Throws an exception if the value has not been initialized. Object does not allow null. +/// +public string @Abbreviation { get { return @abbreviationColumnValue.Value; } set { @abbreviationColumnValue.Value = value; } } +/// +/// Indicates whether or not the value for the Abbreviation has been set since object creation or the last call to Execute, whichever was latest. +/// +public bool @AbbreviationHasChanged { get { return @abbreviationColumnValue.Changed; } } +/// +/// Creates a modification object in insert mode, which can be used to do a piecemeal insert of a new row in the CommandRunner.DatabaseAbstraction.Table table. +/// +public static dbo.@StatesModification CreateForInsert() { +return new dbo.@StatesModification { modType = ModificationType.Insert }; +} +/// +/// Creates a modification object in update mode with the specified conditions, which can be used to do a piecemeal update of the dbo.States table. +/// +public static dbo.@StatesModification CreateForUpdate( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var mod = new dbo.@StatesModification { modType = ModificationType.Update, conditions = getConditionList( requiredCondition, additionalConditions ) }; +foreach( var condition in mod.conditions ) { +if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@StateId ) +mod.@stateIdColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@StateId ).Value; +else if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@StateName ) +mod.@stateNameColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@StateName ).Value; +else if( condition is CommandConditions.dbo.@StatesTableEqualityConditions.@Abbreviation ) +mod.@abbreviationColumnValue.Value = ( condition as CommandConditions.dbo.@StatesTableEqualityConditions.@Abbreviation ).Value; +} + +mod.markColumnValuesUnchanged(); +return mod; +} +/// +/// Creates a modification object in single-row update mode with the specified current data. All column values in this object will have HasChanged = false, despite being initialized. This object can then be used to do a piecemeal update of the dbo.States table. +/// +public static dbo.@StatesModification CreateForSingleRowUpdate( int @stateId, string @stateName, string @abbreviation ) { +var mod = new dbo.@StatesModification { modType = ModificationType.Update }; +mod.conditions = new List(); +mod.conditions.Add( new CommandConditions.dbo.@StatesTableEqualityConditions.@StateId( @stateId ) ); +mod.@stateIdColumnValue.Value = @stateId; +mod.@stateNameColumnValue.Value = @stateName; +mod.@abbreviationColumnValue.Value = @abbreviation; +mod.markColumnValuesUnchanged(); +return mod; +} +private static List getConditionList( CommandConditions.dbo.StatesTableCondition requiredCondition, params CommandConditions.dbo.StatesTableCondition[] additionalConditions ) { +var conditions = new List(); +conditions.Add( requiredCondition ); +foreach( var condition in additionalConditions ) +conditions.Add( condition ); +return conditions; +} +private @StatesModification() {} +/// +/// Sets all column values. This is useful for enforcing the number of arguments when deferred execution is needed. +/// +/// Object does not allow null. +/// Object does not allow null. +/// Object does not allow null. +public void SetAllData( int @stateId, string @stateName, string @abbreviation ) { +this.@stateIdColumnValue.Value = @stateId; +this.@stateNameColumnValue.Value = @stateName; +this.@abbreviationColumnValue.Value = @abbreviation; +} +/// +/// Executes this dbo.States modification, persisting all changes. Executes any pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void Execute() { +DataAccessState.Current.DatabaseConnection.ExecuteInTransaction( () => { +var frozenModType = modType; +if( frozenModType == ModificationType.Insert ) +preInsert(); +else if( frozenModType == ModificationType.Update ) +preUpdate(); +executeInsertOrUpdate(); +if( frozenModType == ModificationType.Insert ) +postInsert(); +else if( frozenModType == ModificationType.Update ) +postUpdate(); +markColumnValuesUnchanged(); +} ); +} +partial void preInsert(); +partial void preUpdate(); +/// +/// Executes this dbo.States modification, persisting all changes. Does not execute pre-insert, pre-update, post-insert, or post-update logic that may exist in the class. +/// +public void ExecuteWithoutAdditionalLogic() { +executeInsertOrUpdate(); +markColumnValuesUnchanged(); +} +private void executeInsertOrUpdate() { +try { +if( modType == ModificationType.Insert ) { +var insert = new InlineInsert( "dbo.States", false, 5 ); +addColumnModifications( insert ); +insert.Execute( DataAccessState.Current.DatabaseConnection ); +if( !@StateIdHasChanged ) return; +modType = ModificationType.Update; +conditions = new List(); +conditions.Add( new CommandConditions.dbo.@StatesTableEqualityConditions.@StateId( @StateId ) ); +} +else { +var update = new InlineUpdate( "dbo.States", 5 ); +addColumnModifications( update ); +conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) ); +update.Execute( DataAccessState.Current.DatabaseConnection ); +} +} +catch(Exception e) { +rethrowAsDataModificationExceptionIfNecessary( e ); +throw; +} +} +private void addColumnModifications( InlineDbModificationCommand cmd ) { +if( @stateIdColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "StateId", new DbParameterValue( @StateId, "Int" ) ) ); +if( @stateNameColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "StateName", new DbParameterValue( @StateName, "NVarChar" ) ) ); +if( @abbreviationColumnValue.Changed ) +cmd.AddColumnModification( new InlineDbCommandColumnValue( "Abbreviation", new DbParameterValue( @Abbreviation, "NVarChar" ) ) ); +} +private static void rethrowAsDataModificationExceptionIfNecessary( System.Exception e ) { +var constraintNamesToViolationErrorMessages = new Dictionary(); +populateConstraintNamesToViolationErrorMessages( constraintNamesToViolationErrorMessages ); +foreach( var pair in constraintNamesToViolationErrorMessages ) +if( e.GetBaseException().Message.ToLower().Contains( pair.Key.ToLower() ) ) throw new DataModificationException( pair.Value ); +} +static partial void populateConstraintNamesToViolationErrorMessages( Dictionary constraintNamesToViolationErrorMessages ); +partial void postInsert(); +partial void postUpdate(); +private void markColumnValuesUnchanged() { +@stateIdColumnValue.ClearChanged(); +@stateNameColumnValue.ClearChanged(); +@abbreviationColumnValue.ClearChanged(); +} +} +} +} + +namespace Tdl.TestGeneration.DataAccess.Retrieval { +/// +/// This object holds the values returned from a PrimarySequence query. +/// +public static partial class PrimarySequenceRetrieval { +internal class BasicRow { +private readonly int @__id; +internal BasicRow( DbDataReader reader ) { +@__id = (int)reader.GetValue( 0 ); +} +internal int @Id { get { return @__id; } } +} +/// +/// Holds data for a row of this result. +/// +public partial class Row: IEquatable { +private readonly BasicRow __basicRow; +internal Row( BasicRow basicRow ) { +__basicRow = basicRow; +} +/// +/// This object will never be null. +/// +public int @Id { get { return __basicRow.@Id; } } +public override int GetHashCode() { +return @Id.GetHashCode(); +} +public static bool operator == ( Row row1, Row row2 ) => Equals( row1, row2 ); + public static bool operator !=( Row row1, Row row2 ) => !Equals( row1, row2 ); +public override bool Equals( object obj ) { +return Equals( obj as Row ); +} +public bool Equals( Row other ) { +if( other == null ) return false; +return @Id == other.@Id; +} +} +private partial class Cache { +internal static Cache Current { get { return DataAccessState.Current.GetCacheValue( "PrimarySequenceQueryRetrieval", () => new Cache() ); } } +private readonly ParameterlessQueryCache rowsNextQuery = new ParameterlessQueryCache(); +private Cache() {} +internal ParameterlessQueryCache RowsNextQuery { get { return rowsNextQuery; } } +} +private const string selectFromClause = @"SELECT NEXT VALUE FOR PrimarySequence as Id "; +/// +/// Queries the database and returns the full results collection immediately. +/// +public static IEnumerable GetRowsNext( ) { +return Cache.Current.RowsNextQuery.GetResultSet( () => { +var cmd = DataAccessState.Current.DatabaseConnection.DatabaseInfo.CreateCommand(5); +cmd.CommandText = selectFromClause +;var results = new List(); +DataAccessState.Current.DatabaseConnection.ExecuteReaderCommand( cmd, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } ); +foreach( var i in results ) +updateSingleRowCaches( i ); +return results; +} ); +} +static partial void updateSingleRowCaches( Row row ); +} +} + diff --git a/TypedDataLayer.sln b/TypedDataLayer.sln index f774a37..0d18f60 100644 --- a/TypedDataLayer.sln +++ b/TypedDataLayer.sln @@ -7,25 +7,65 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TypedDataLayer", "TypedData EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandRunner", "CommandRunner\CommandRunner.csproj", "{A81039DF-DEF4-40B8-A770-6DD3450E0961}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestTdlGeneration", "TestTdlGeneration\TestTdlGeneration.csproj", "{3718CC44-0F9A-46B2-A56F-7E56032DB725}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestTdlDml", "TestTdlDml\TestTdlDml.csproj", "{52F1219A-7EE4-40AF-B12A-2A4E01E750C4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 + Debug-TypedDataLayer|Any CPU = Debug-TypedDataLayer|Any CPU Debug-TypedDataLayer|x64 = Debug-TypedDataLayer|x64 + Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug|Any CPU.Build.0 = Debug|Any CPU {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug|x64.ActiveCfg = Debug|Any CPU {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug|x64.Build.0 = Debug|Any CPU + {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug-TypedDataLayer|Any CPU.ActiveCfg = Debug|Any CPU + {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug-TypedDataLayer|Any CPU.Build.0 = Debug|Any CPU {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug-TypedDataLayer|x64.ActiveCfg = Debug|Any CPU {86A9C472-70EA-4DD1-B36E-5276C754E720}.Debug-TypedDataLayer|x64.Build.0 = Debug|Any CPU + {86A9C472-70EA-4DD1-B36E-5276C754E720}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86A9C472-70EA-4DD1-B36E-5276C754E720}.Release|Any CPU.Build.0 = Release|Any CPU {86A9C472-70EA-4DD1-B36E-5276C754E720}.Release|x64.ActiveCfg = Release|Any CPU {86A9C472-70EA-4DD1-B36E-5276C754E720}.Release|x64.Build.0 = Release|Any CPU + {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Debug|Any CPU.ActiveCfg = Debug|x64 {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Debug|x64.ActiveCfg = Debug|x64 {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Debug|x64.Build.0 = Debug|x64 + {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Debug-TypedDataLayer|Any CPU.ActiveCfg = Debug-TypedDataLayer|x64 {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Debug-TypedDataLayer|x64.ActiveCfg = Debug-TypedDataLayer|x64 {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Debug-TypedDataLayer|x64.Build.0 = Debug-TypedDataLayer|x64 + {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Release|Any CPU.ActiveCfg = Release|x64 {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Release|x64.ActiveCfg = Release|x64 {A81039DF-DEF4-40B8-A770-6DD3450E0961}.Release|x64.Build.0 = Release|x64 + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug|x64.ActiveCfg = Debug|x64 + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug|x64.Build.0 = Debug|x64 + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug-TypedDataLayer|Any CPU.ActiveCfg = Debug|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug-TypedDataLayer|Any CPU.Build.0 = Debug|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug-TypedDataLayer|x64.ActiveCfg = Debug|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Debug-TypedDataLayer|x64.Build.0 = Debug|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Release|Any CPU.Build.0 = Release|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Release|x64.ActiveCfg = Release|Any CPU + {3718CC44-0F9A-46B2-A56F-7E56032DB725}.Release|x64.Build.0 = Release|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug|x64.ActiveCfg = Debug|x64 + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug|x64.Build.0 = Debug|x64 + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug-TypedDataLayer|Any CPU.ActiveCfg = Debug|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug-TypedDataLayer|Any CPU.Build.0 = Debug|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug-TypedDataLayer|x64.ActiveCfg = Debug|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Debug-TypedDataLayer|x64.Build.0 = Debug|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Release|Any CPU.Build.0 = Release|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Release|x64.ActiveCfg = Release|Any CPU + {52F1219A-7EE4-40AF-B12A-2A4E01E750C4}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TypedDataLayer/Collections/Cache.cs b/TypedDataLayer/Collections/Cache.cs index 065fbb0..42cf230 100644 --- a/TypedDataLayer/Collections/Cache.cs +++ b/TypedDataLayer/Collections/Cache.cs @@ -57,6 +57,7 @@ public ValType GetOrAdd( KeyType key, Func newValueCreator ) { value = newValueCreator(); dictionary.Add( key, value ); } + // GMS NOTE: Debug write cache hits? return value; } diff --git a/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineInsert.cs b/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineInsert.cs index d1f653d..e42c7d3 100644 --- a/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineInsert.cs +++ b/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineInsert.cs @@ -39,10 +39,11 @@ public object Execute( DBConnection cn ) { if( columnModifications.Count == 0 ) sb.Append( " DEFAULT VALUES" ); else { - sb.Append( "(" ); + sb.Append( '(' ); foreach( var columnMod in columnModifications ) { + sb.Append( '[' ); sb.Append( columnMod.ColumnName ); - sb.Append( ", " ); + sb.Append( "], " ); } sb.Remove( sb.Length - 2, 2 ); @@ -51,12 +52,12 @@ public object Execute( DBConnection cn ) { foreach( var columnMod in columnModifications ) { var parameter = columnMod.GetParameter(); sb.Append( parameter.GetNameForCommandText( cn.DatabaseInfo ) ); - sb.Append( "," ); + sb.Append( ',' ); cmd.Parameters.Add( parameter.GetAdoDotNetParameter( cn.DatabaseInfo ) ); } sb.Remove( sb.Length - 1, 1 ); - sb.Append( ")" ); + sb.Append( ')' ); } cmd.CommandText = sb.ToString(); diff --git a/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineUpdate.cs b/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineUpdate.cs index 715c904..02dc54b 100644 --- a/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineUpdate.cs +++ b/TypedDataLayer/DataAccess/CommandWriting/Commands/InlineUpdate.cs @@ -53,8 +53,9 @@ public int Execute( DBConnection cn ) { foreach( var columnMod in columnModifications ) { var parameter = columnMod.GetParameter( name: GetParamNameFromNumber( paramNumber++ ) ); + sb.Append( '[' ); sb.Append( columnMod.ColumnName ); - sb.Append( " = " ); + sb.Append( "] = " ); sb.Append( parameter.GetNameForCommandText( cn.DatabaseInfo ) ); sb.Append( ", " ); cmd.Parameters.Add( parameter.GetAdoDotNetParameter( cn.DatabaseInfo ) ); diff --git a/TypedDataLayer/Tools/StringTools.cs b/TypedDataLayer/Tools/StringTools.cs index 94db2b9..9ec77a7 100644 --- a/TypedDataLayer/Tools/StringTools.cs +++ b/TypedDataLayer/Tools/StringTools.cs @@ -4,6 +4,7 @@ using System.Text; using System.Text.RegularExpressions; +// GMS NOTE: Should really reference TEWL. namespace TypedDataLayer.Tools { /// /// Provides helpful string methods.