diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/CommandHandlers/AddFibonacciNumberCommandHandler.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/CommandHandlers/AddFibonacciNumberCommandHandler.cs new file mode 100644 index 00000000..879b16ad --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/CommandHandlers/AddFibonacciNumberCommandHandler.cs @@ -0,0 +1,98 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.Command; +using RapidField.SolidInstruments.Core.Concurrency; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Commands; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories; +using RapidField.SolidInstruments.ObjectComposition; +using System; +using System.Linq; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.CommandHandlers +{ + /// + /// Processes a command that adds a Fibonacci number to the Simulated database. + /// + public sealed class AddFibonacciNumberCommandHandler : SimulatedCommandHandler + { + /// + /// Initializes a new instance of the class. + /// + /// + /// A processing intermediary that is used to process sub-commands. + /// + /// + /// The factory that produces data access repositories for the handler. + /// + /// + /// is -or- is + /// . + /// + public AddFibonacciNumberCommandHandler(ICommandMediator mediator, SimulatedRepositoryFactory repositoryFactory) + : base(mediator, repositoryFactory) + { + return; + } + + /// + /// Releases all resources consumed by the current . + /// + /// + /// A value indicating whether or not managed resources should be released. + /// + protected override void Dispose(Boolean disposing) => base.Dispose(disposing); + + /// + /// Processes the specified command. + /// + /// + /// The command to process. + /// + /// + /// A processing intermediary that is used to process sub-commands. Do not process using + /// , as doing so will generally result in infinite-looping. + /// + /// + /// An object that provides access to data access repositories. + /// + /// + /// A token that represents and manages contextual thread safety. + /// + protected override void Process(AddFibonacciNumberCommand command, ICommandMediator mediator, IFactoryProducedInstanceGroup repositories, IConcurrencyControlToken controlToken) + { + var fibonacciNumberSeries = NumberSeries.Named.Fibonacci; + var numberRepository = repositories.Get(); + var number = numberRepository.FindByValue(command.NumberValue); + + if (number is null) + { + number = new Number() + { + Identifier = Guid.NewGuid(), + Value = command.NumberValue + }; + + numberRepository.Add(number); + } + + var numberSeriesNumberRespository = repositories.Get(); + var numberSeriesNumber = numberSeriesNumberRespository.FindWhere(entity => entity.Number.Value == number.Value && entity.NumberSeriesIdentifier == fibonacciNumberSeries.Identifier).SingleOrDefault(); + + if (numberSeriesNumber is null) + { + numberSeriesNumber = new NumberSeriesNumber() + { + Identifier = Guid.NewGuid(), + Number = number, + NumberIdentifier = number.Identifier, + NumberSeriesIdentifier = fibonacciNumberSeries.Identifier + }; + + numberSeriesNumberRespository.Add(numberSeriesNumber); + } + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/CommandHandlers/GetFibonacciNumberValuesCommandHandler.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/CommandHandlers/GetFibonacciNumberValuesCommandHandler.cs new file mode 100644 index 00000000..66aab7b3 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/CommandHandlers/GetFibonacciNumberValuesCommandHandler.cs @@ -0,0 +1,74 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.Command; +using RapidField.SolidInstruments.Core.Concurrency; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Commands; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories; +using RapidField.SolidInstruments.ObjectComposition; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.CommandHandlers +{ + /// + /// Processes a command that gets all of the Fibonacci number values from the Simulated database. + /// + public sealed class GetFibonacciNumberValuesCommandHandler : SimulatedCommandHandler> + { + /// + /// Initializes a new instance of the class. + /// + /// + /// A processing intermediary that is used to process sub-commands. + /// + /// + /// The factory that produces data access repositories for the handler. + /// + /// + /// is -or- is + /// . + /// + public GetFibonacciNumberValuesCommandHandler(ICommandMediator mediator, SimulatedRepositoryFactory repositoryFactory) + : base(mediator, repositoryFactory) + { + return; + } + + /// + /// Releases all resources consumed by the current . + /// + /// + /// A value indicating whether or not managed resources should be released. + /// + protected override void Dispose(Boolean disposing) => base.Dispose(disposing); + + /// + /// Processes the specified command. + /// + /// + /// The command to process. + /// + /// + /// A processing intermediary that is used to process sub-commands. Do not process using + /// , as doing so will generally result in infinite-looping. + /// + /// + /// An object that provides access to data access repositories. + /// + /// + /// A token that represents and manages contextual thread safety. + /// + /// + /// The result that is emitted when processing the command. + /// + protected sealed override IEnumerable Process(GetFibonacciNumberValuesCommand command, ICommandMediator mediator, IFactoryProducedInstanceGroup repositories, IConcurrencyControlToken controlToken) + { + var numberSeriesNumberRepository = repositories.Get(); + return numberSeriesNumberRepository.FindWhere(entity => entity.NumberSeries.Identifier == NumberSeries.Named.Fibonacci.Identifier).Select(entity => entity.Number.Value).ToList(); + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Commands/AddFibonacciNumberCommand.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Commands/AddFibonacciNumberCommand.cs new file mode 100644 index 00000000..8f4c7990 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Commands/AddFibonacciNumberCommand.cs @@ -0,0 +1,41 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess; +using System; +using System.Diagnostics; +using System.Runtime.Serialization; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Commands +{ + /// + /// Represents a data access command that adds a specified numeric value to the Fibonacci series. + /// + [DataContract] + public sealed class AddFibonacciNumberCommand : DataAccessCommand + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The value of the Fibonacci number that is added to the series. + /// + [DebuggerHidden] + internal AddFibonacciNumberCommand(Int64 numberValue) + : base() + { + NumberValue = numberValue; + } + + /// + /// Gets or sets the value of the Fibonacci number that is added to the series. + /// + [DataMember] + public Int64 NumberValue + { + get; + set; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Commands/GetFibonacciNumberValuesCommand.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Commands/GetFibonacciNumberValuesCommand.cs new file mode 100644 index 00000000..2382c497 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Commands/GetFibonacciNumberValuesCommand.cs @@ -0,0 +1,29 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.Serialization; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Commands +{ + /// + /// Represents a data access command that returns the numeric values for the Fibonacci series. + /// + [DataContract] + public sealed class GetFibonacciNumberValuesCommand : DataAccessCommand> + { + /// + /// Initializes a new instance of the class. + /// + [DebuggerHidden] + internal GetFibonacciNumberValuesCommand() + : base() + { + return; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/Number.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/Number.cs new file mode 100644 index 00000000..162de452 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/Number.cs @@ -0,0 +1,79 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.Core.ArgumentValidation; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models; +using System; +using System.ComponentModel.DataAnnotations; +using System.Diagnostics; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities +{ + /// + /// Represents an integer number. + /// + public sealed class Number : INumber + { + /// + /// Initializes a new instance of the class. + /// + [DebuggerHidden] + internal Number() + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A model that is used to hydrate the new object. + /// + [DebuggerHidden] + internal Number(INumber model) + : this(model.Identifier, model.Value) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A unique identifier for the entity. + /// + /// + /// The value of the number. + /// + /// + /// is equal to . + /// + [DebuggerHidden] + private Number(Guid identifier, Int64 value) + { + Identifier = identifier.RejectIf().IsEqualToValue(Guid.Empty, nameof(identifier)); + Value = value; + } + + /// + /// Gets or sets a unique identifier for the entity. + /// + [Key] + public Guid Identifier + { + get; + set; + } + + /// + /// Gets or sets the value of the number. + /// + [Required] + public Int64 Value + { + get; + set; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/NumberSeries.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/NumberSeries.cs new file mode 100644 index 00000000..6939a746 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/NumberSeries.cs @@ -0,0 +1,102 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.Core; +using RapidField.SolidInstruments.Core.ArgumentValidation; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models; +using System; +using System.ComponentModel.DataAnnotations; +using System.Diagnostics; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities +{ + /// + /// Represents a sequential series of integer numbers. + /// + public sealed class NumberSeries : INumberSeries + { + /// + /// Initializes a new instance of the class. + /// + [DebuggerHidden] + internal NumberSeries() + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A model that is used to hydrate the new object. + /// + [DebuggerHidden] + internal NumberSeries(INumberSeries model) + : this(model.Identifier, model.Name) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A unique identifier for the entity. + /// + /// + /// The name of the series. + /// + /// + /// is empty. + /// + /// + /// is . + /// + /// + /// is equal to . + /// + [DebuggerHidden] + private NumberSeries(Guid identifier, String name) + { + Identifier = identifier.RejectIf().IsEqualToValue(Guid.Empty, nameof(identifier)); + Name = name.RejectIf().IsNullOrEmpty(nameof(name)); + } + + /// + /// Gets or sets a unique identifier for the entity. + /// + [Key] + public Guid Identifier + { + get; + set; + } + + /// + /// Gets or sets the name of the series. + /// + [Required] + public String Name + { + get; + set; + } + + /// + /// Contains a collection of known records. + /// + internal static class Named + { + /// + /// Represents the Fibonacci number series. + /// + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + internal static NumberSeries Fibonacci => new NumberSeries() + { + Identifier = Guid.Parse("1100d8c5-a70c-4db2-833d-33638e453082"), + Name = "Fibonacci" + }; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/NumberSeriesNumber.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/NumberSeriesNumber.cs new file mode 100644 index 00000000..d16cde68 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Entities/NumberSeriesNumber.cs @@ -0,0 +1,115 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.Core.ArgumentValidation; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models; +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Diagnostics; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities +{ + /// + /// Represents an integer number belonging to a specific number series. + /// + public sealed class NumberSeriesNumber : INumberSeriesNumber + { + /// + /// Initializes a new instance of the class. + /// + [DebuggerHidden] + internal NumberSeriesNumber() + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A model that is used to hydrate the new object. + /// + [DebuggerHidden] + internal NumberSeriesNumber(INumberSeriesNumber model) + : this(model.Identifier, model.NumberIdentifier, model.NumberSeriesIdentifier) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A unique identifier for the entity. + /// + /// + /// A unique identifier for the associated number. + /// + /// + /// A unique identifier for the associated number series. + /// + /// + /// is equal to -or- is equal + /// to -or- is equal to . + /// + [DebuggerHidden] + private NumberSeriesNumber(Guid identifier, Guid numberIdentifier, Guid numberSeriesIdentifier) + { + Identifier = identifier.RejectIf().IsEqualToValue(Guid.Empty, nameof(identifier)); + NumberIdentifier = numberIdentifier.RejectIf().IsEqualToValue(Guid.Empty, nameof(numberIdentifier)); + NumberSeriesIdentifier = numberSeriesIdentifier.RejectIf().IsEqualToValue(Guid.Empty, nameof(numberSeriesIdentifier)); + } + + /// + /// Gets or sets a unique identifier for the entity. + /// + [Key] + public Guid Identifier + { + get; + set; + } + + /// + /// Gets or sets the associated number. + /// + [ForeignKey(nameof(NumberIdentifier))] + public Number Number + { + get; + set; + } + + /// + /// Gets or sets a unique identifier for the associated number. + /// + [Required] + public Guid NumberIdentifier + { + get; + set; + } + + /// + /// Gets or sets the associated number series. + /// + [ForeignKey(nameof(NumberSeriesIdentifier))] + public NumberSeries NumberSeries + { + get; + set; + } + + /// + /// Gets or sets a unique identifier for the associated number series. + /// + [Required] + public Guid NumberSeriesIdentifier + { + get; + set; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkCommandHandlerTests.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkCommandHandlerTests.cs index f329a913..ed0da5c4 100644 --- a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkCommandHandlerTests.cs +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkCommandHandlerTests.cs @@ -6,9 +6,9 @@ using Microsoft.Extensions.Configuration; using Microsoft.VisualStudio.TestTools.UnitTesting; using RapidField.SolidInstruments.Command; -using RapidField.SolidInstruments.Example.DatabaseModel; -using RapidField.SolidInstruments.Example.DatabaseModel.CommandHandlers; -using RapidField.SolidInstruments.Example.DatabaseModel.Commands; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.CommandHandlers; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Commands; using RapidField.SolidInstruments.TextEncoding; using System; @@ -34,9 +34,9 @@ public void FunctionalLifeSpanTest_ShouldProduceDesiredResults() var scope = engine.Container.CreateScope(); var commandMediator = scope.Resolve(); - using (var context = new ExampleInMemoryContext(configuration, databaseName).WithTestData()) + using (var context = new SimulatedInMemoryContext(configuration, databaseName).WithTestData()) { - using (var repositoryFactory = new ExampleRepositoryFactory(context, configuration)) + using (var repositoryFactory = new SimulatedRepositoryFactory(context, configuration)) { using (var commandHandler = new GetFibonacciNumberValuesCommandHandler(commandMediator, repositoryFactory)) { diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkRepositoryTests.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkRepositoryTests.cs index b9ce5fce..991cd299 100644 --- a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkRepositoryTests.cs +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/EntityFrameworkRepositoryTests.cs @@ -5,8 +5,8 @@ using FluentAssertions; using Microsoft.Extensions.Configuration; using Microsoft.VisualStudio.TestTools.UnitTesting; -using RapidField.SolidInstruments.Example.DatabaseModel; -using RapidField.SolidInstruments.Example.DatabaseModel.Repositories; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories; using RapidField.SolidInstruments.TextEncoding; using System; using System.Linq; @@ -25,7 +25,7 @@ public void FunctionalLifeSpanTest_ShouldProduceDesiredResults() var fibonacciNumberSeriesName = "Fibonacci"; var fibonacciNumberSeriesValues = new Int64[] { 0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; - using (var context = new ExampleInMemoryContext(configuration, databaseName).WithTestData()) + using (var context = new SimulatedInMemoryContext(configuration, databaseName).WithTestData()) { using (var numberSeriesRepository = new NumberSeriesRepository(context)) { diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberExtensions.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberExtensions.cs new file mode 100644 index 00000000..5abbf612 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberExtensions.cs @@ -0,0 +1,26 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Extensions +{ + /// + /// Extends the interface with type conversion features. + /// + public static class INumberExtensions + { + /// + /// Converts the specified model to a messaging model. + /// + /// + /// The current . + /// + /// + /// The converted object. + /// + public static Number ToSimulatedDatabaseEntity(this INumber target) => new Number(target); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberSeriesExtensions.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberSeriesExtensions.cs new file mode 100644 index 00000000..68b5ad64 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberSeriesExtensions.cs @@ -0,0 +1,26 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Extensions +{ + /// + /// Extends the interface with type conversion features. + /// + public static class INumberSeriesExtensions + { + /// + /// Converts the specified model to a messaging model. + /// + /// + /// The current . + /// + /// + /// The converted object. + /// + public static NumberSeries ToSimulatedDatabaseEntity(this INumberSeries target) => new NumberSeries(target); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberSeriesNumberExtensions.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberSeriesNumberExtensions.cs new file mode 100644 index 00000000..a978e6e6 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Extensions/INumberSeriesNumberExtensions.cs @@ -0,0 +1,26 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Extensions +{ + /// + /// Extends the interface with type conversion features. + /// + public static class INumberSeriesNumberExtensions + { + /// + /// Converts the specified model to a messaging model. + /// + /// + /// The current . + /// + /// + /// The converted object. + /// + public static NumberSeriesNumber ToSimulatedDatabaseEntity(this INumberSeriesNumber target) => new NumberSeriesNumber(target); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumber.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumber.cs new file mode 100644 index 00000000..7cf8a14c --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumber.cs @@ -0,0 +1,30 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using System; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models +{ + /// + /// Represents an integer number. + /// + public interface INumber + { + /// + /// Gets a unique identifier for the entity. + /// + public Guid Identifier + { + get; + } + + /// + /// Gets the value of the number. + /// + public Int64 Value + { + get; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumberSeries.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumberSeries.cs new file mode 100644 index 00000000..b20e651c --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumberSeries.cs @@ -0,0 +1,30 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using System; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models +{ + /// + /// Represents a sequential series of integer numbers. + /// + public interface INumberSeries + { + /// + /// Gets a unique identifier for the entity. + /// + public Guid Identifier + { + get; + } + + /// + /// Gets the name of the series. + /// + public String Name + { + get; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumberSeriesNumber.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumberSeriesNumber.cs new file mode 100644 index 00000000..2e56d955 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Models/INumberSeriesNumber.cs @@ -0,0 +1,38 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using System; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Models +{ + /// + /// Represents an integer number belonging to a specific number series. + /// + public interface INumberSeriesNumber + { + /// + /// Gets a unique identifier for the entity. + /// + public Guid Identifier + { + get; + } + + /// + /// Gets a unique identifier for the associated number. + /// + public Guid NumberIdentifier + { + get; + } + + /// + /// Gets a unique identifier for the associated number series. + /// + public Guid NumberSeriesIdentifier + { + get; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.csproj b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.csproj index a9797c8f..ba3492ee 100644 --- a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.csproj +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.csproj @@ -24,9 +24,11 @@ Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in - + + + \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberRepository.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberRepository.cs new file mode 100644 index 00000000..ad4ef7c0 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberRepository.cs @@ -0,0 +1,56 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using System; +using System.Linq; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories +{ + /// + /// Represents a repository for the entity type. + /// + public sealed class NumberRepository : EntityFrameworkRepository + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The database session for the repository. + /// + /// + /// is . + /// + public NumberRepository(SimulatedContext context) + : base(context) + { + return; + } + + /// + /// Finds the with the specified identifier. + /// + /// + /// The identifier to find. + /// + /// + /// The with the specified value, or if the is not + /// found. + /// + public Number FindByIdentifier(Guid identifier) => FindWhere(entity => entity.Identifier == identifier).SingleOrDefault(); + + /// + /// Finds the with the specified value. + /// + /// + /// The value to find. + /// + /// + /// The with the specified value, or if the is not + /// found. + /// + public Number FindByValue(Int64 value) => FindWhere(entity => entity.Value == value).SingleOrDefault(); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberSeriesNumberRepository.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberSeriesNumberRepository.cs new file mode 100644 index 00000000..bda6ab6b --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberSeriesNumberRepository.cs @@ -0,0 +1,44 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using System; +using System.Linq; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories +{ + /// + /// Represents a repository for the entity type. + /// + public sealed class NumberSeriesNumberRepository : EntityFrameworkRepository + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The database session for the repository. + /// + /// + /// is . + /// + public NumberSeriesNumberRepository(SimulatedContext context) + : base(context) + { + return; + } + + /// + /// Finds the with the specified identifier. + /// + /// + /// The identifier to find. + /// + /// + /// The with the specified value, or if the + /// is not found. + /// + public NumberSeriesNumber FindByIdentifier(Guid identifier) => FindWhere(entity => entity.Identifier == identifier).SingleOrDefault(); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberSeriesRepository.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberSeriesRepository.cs new file mode 100644 index 00000000..e33865a4 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/Repositories/NumberSeriesRepository.cs @@ -0,0 +1,56 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using System; +using System.Linq; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories +{ + /// + /// Represents a repository for the entity type. + /// + public sealed class NumberSeriesRepository : EntityFrameworkRepository + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The database session for the repository. + /// + /// + /// is . + /// + public NumberSeriesRepository(SimulatedContext context) + : base(context) + { + return; + } + + /// + /// Finds the with the specified identifier. + /// + /// + /// The identifier to find. + /// + /// + /// The with the specified identifier, or if the + /// is not found. + /// + public NumberSeries FindByIdentifier(Guid identifier) => FindWhere(entity => entity.Identifier == identifier).SingleOrDefault(); + + /// + /// Finds the with the specified name. + /// + /// + /// The name to find. + /// + /// + /// The with the specified name, or if the + /// is not found. + /// + public NumberSeries FindByName(String name) => FindWhere(entity => entity.Name == name).SingleOrDefault(); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedCommandHandler.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedCommandHandler.cs new file mode 100644 index 00000000..2c4717e9 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedCommandHandler.cs @@ -0,0 +1,135 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.Command; +using RapidField.SolidInstruments.DataAccess; +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using System; +using System.Data; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Processes Simulated data access commands. + /// + /// + /// The type of the data access command that is processed by the handler. + /// + public abstract class SimulatedCommandHandler : EntityFrameworkCommandHandler + where TCommand : class, IDataAccessCommand + { + /// + /// Initializes a new instance of the class. + /// + /// + /// A processing intermediary that is used to process sub-commands. + /// + /// + /// The factory that produces data access repositories for the handler. + /// + /// + /// is -or- is + /// . + /// + protected SimulatedCommandHandler(ICommandMediator mediator, SimulatedRepositoryFactory repositoryFactory) + : base(mediator, repositoryFactory) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A processing intermediary that is used to process sub-commands. + /// + /// + /// The factory that produces data access repositories for the handler. + /// + /// + /// The isolation level for the transaction, or to use the database default. The + /// default value is . + /// + /// + /// is -or- is + /// . + /// + protected SimulatedCommandHandler(ICommandMediator mediator, SimulatedRepositoryFactory repositoryFactory, IsolationLevel isolationLevel) + : base(mediator, repositoryFactory, isolationLevel) + { + return; + } + + /// + /// Releases all resources consumed by the current . + /// + /// + /// A value indicating whether or not managed resources should be released. + /// + protected override void Dispose(Boolean disposing) => base.Dispose(disposing); + } + + /// + /// Processes Simulated data access commands. + /// + /// + /// The type of the data access command that is processed by the handler. + /// + /// + /// The type of the result that is emitted by the handler when processing a data access command. + /// + public abstract class SimulatedCommandHandler : EntityFrameworkCommandHandler + where TCommand : class, IDataAccessCommand + { + /// + /// Initializes a new instance of the class. + /// + /// + /// A processing intermediary that is used to process sub-commands. + /// + /// + /// The factory that produces data access repositories for the handler. + /// + /// + /// is -or- is + /// . + /// + protected SimulatedCommandHandler(ICommandMediator mediator, SimulatedRepositoryFactory repositoryFactory) + : base(mediator, repositoryFactory) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// A processing intermediary that is used to process sub-commands. + /// + /// + /// The factory that produces data access repositories for the handler. + /// + /// + /// The isolation level for the transaction, or to use the database default. The + /// default value is . + /// + /// + /// is -or- is + /// . + /// + protected SimulatedCommandHandler(ICommandMediator mediator, SimulatedRepositoryFactory repositoryFactory, IsolationLevel isolationLevel) + : base(mediator, repositoryFactory, isolationLevel) + { + return; + } + + /// + /// Releases all resources consumed by the current . + /// + /// + /// A value indicating whether or not managed resources should be released. + /// + protected override void Dispose(Boolean disposing) => base.Dispose(disposing); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedCommands.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedCommands.cs new file mode 100644 index 00000000..3221b99b --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedCommands.cs @@ -0,0 +1,34 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.Core; +using RapidField.SolidInstruments.DataAccess; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Commands; +using System; +using System.Collections.Generic; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Exposes a collection of data access commands for the Simulated database. + /// + public static class SimulatedCommands + { + /// + /// Creates a data access command that adds a specified numeric value to the Fibonacci series. + /// + /// + /// The value of the Fibonacci number that is added to the series. + /// + public static IDataAccessCommand AddFibonacciNumber(Int64 numberValue) => new AddFibonacciNumberCommand(numberValue); + + /// + /// Creates a data access command that returns the numeric values for the Fibonacci series. + /// + /// + /// The numeric values for the Fibonacci series. + /// + public static IDataAccessCommand> GetFibonacciNumberValues() => new GetFibonacciNumberValuesCommand(); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedContext.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedContext.cs new file mode 100644 index 00000000..fcb08631 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedContext.cs @@ -0,0 +1,181 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using RapidField.SolidInstruments.Core; +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using System; +using System.Configuration; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Represents a connection to a prototypical database. + /// + public class SimulatedContext : ConfiguredContext + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// is . + /// + /// + /// The constructor was unable to determine the appropriate connection type by evaluating the connection string. + /// + public SimulatedContext(IConfiguration applicationConfiguration) + : base(applicationConfiguration) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// The database type of the backing database, or to determine the connection + /// type dynamically based on the format of the connection string. + /// + /// + /// is . + /// + /// + /// is equal to and the constructor was + /// unable to determine the appropriate connection type by evaluating the connection string. + /// + public SimulatedContext(IConfiguration applicationConfiguration, ContextDatabaseType databaseType) + : base(applicationConfiguration, databaseType) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// The database type of the backing database, or to determine the connection + /// type dynamically based on the format of the connection string. + /// + /// + /// The name of the backing database, which matches the associated connection string key in + /// . The default value is equal to the context's type name with "Context" + /// trimmed from the end, if found. + /// + /// + /// is empty. + /// + /// + /// is -or- is + /// . + /// + /// + /// is equal to and the constructor was + /// unable to determine the appropriate connection type by evaluating the connection string. + /// + public SimulatedContext(IConfiguration applicationConfiguration, ContextDatabaseType databaseType, String databaseName) + : base(applicationConfiguration, databaseType, databaseName) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// The database type of the backing database, or to determine the connection + /// type dynamically based on the format of the connection string. + /// + /// + /// The query result tracking behavior for the context. The default value is . + /// + /// + /// is . + /// + /// + /// is equal to and the constructor was + /// unable to determine the appropriate connection type by evaluating the connection string. + /// + public SimulatedContext(IConfiguration applicationConfiguration, ContextDatabaseType databaseType, QueryTrackingBehavior trackingBehavior) + : base(applicationConfiguration, databaseType, trackingBehavior) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// The database type of the backing database, or to determine the connection + /// type dynamically based on the format of the connection string. + /// + /// + /// The name of the backing database, which matches the associated connection string key in + /// . The default value is equal to the context's type name with "Context" + /// trimmed from the end, if found. + /// + /// + /// The query result tracking behavior for the context. The default value is . + /// + /// + /// is empty. + /// + /// + /// is -or- is + /// . + /// + /// + /// is equal to and the constructor was + /// unable to determine the appropriate connection type by evaluating the connection string. + /// + public SimulatedContext(IConfiguration applicationConfiguration, ContextDatabaseType databaseType, String databaseName, QueryTrackingBehavior trackingBehavior) + : base(applicationConfiguration, databaseType, databaseName, trackingBehavior) + { + return; + } + + /// + /// Gets or sets a persistent collection of records. + /// + public DbSet Numbers + { + get; + set; + } + + /// + /// Gets or sets a persistent collection of records. + /// + public DbSet NumberSeriesNumbers + { + get; + set; + } + + /// + /// Gets or sets a persistent collection of records. + /// + public DbSet NumerSeries + { + get; + set; + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedDatabaseModelDependencyModule.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedDatabaseModelDependencyModule.cs new file mode 100644 index 00000000..080bb292 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedDatabaseModelDependencyModule.cs @@ -0,0 +1,56 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using RapidField.SolidInstruments.DataAccess.DotNetNative.Extensions; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.CommandHandlers; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Commands; +using RapidField.SolidInstruments.InversionOfControl.DotNetNative; +using System; +using System.Collections.Generic; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Encapsulates configuration for Simulated database model dependencies. + /// + public sealed class SimulatedDatabaseModelDependencyModule : DotNetNativeDependencyModule + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// is . + /// + public SimulatedDatabaseModelDependencyModule(IConfiguration applicationConfiguration) + : base(applicationConfiguration) + { + return; + } + + /// + /// Configures the module. + /// + /// + /// An object that configures containers. + /// + /// + /// Configuration information for the application. + /// + protected override void Configure(ServiceCollection configurator, IConfiguration applicationConfiguration) + { + // Register unit-of-work types. + configurator.AddScoped(provider => new SimulatedInMemoryContext(provider.GetService(), "Simulated")); + configurator.AddScoped(); + + // Register data access command handlers. + configurator.AddDataAccessCommandHandler(); + configurator.AddDataAccessCommandHandler, GetFibonacciNumberValuesCommandHandler>(); + } + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedInMemoryContext.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedInMemoryContext.cs new file mode 100644 index 00000000..5f0a469e --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedInMemoryContext.cs @@ -0,0 +1,123 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.Configuration; +using RapidField.SolidInstruments.Core; +using RapidField.SolidInstruments.Core.ArgumentValidation; +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Entities; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories; +using System; +using System.Diagnostics; +using System.Linq; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Represents a connection to a prototypical, in-memory database. + /// + public sealed class SimulatedInMemoryContext : SimulatedContext + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// The name of the backing database, which matches the associated connection string key in + /// . + /// + /// + /// is empty. + /// + /// + /// is -or- is + /// . + /// + public SimulatedInMemoryContext(IConfiguration applicationConfiguration, String databaseName) + : base(applicationConfiguration, ContextDatabaseType.InMemory, databaseName.RejectIf().IsNullOrEmpty(nameof(databaseName))) + { + return; + } + + /// + /// Populates the current with test data. + /// + /// + /// The current with test data. + /// + [DebuggerHidden] + internal SimulatedInMemoryContext WithTestData() + { + var fibonacciNumberSeriesValues = new Int64[] { 0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; + + using (var numberRepository = new NumberRepository(this)) + { + for (var i = 0; i <= 100; i++) + { + var number = new Number() + { + Identifier = Guid.NewGuid(), + Value = i + }; + + numberRepository.Add(number); + } + + SaveChanges(); + + using (var numberSeriesRepository = new NumberSeriesRepository(this)) + { + numberSeriesRepository.Add(NumberSeries.Named.Fibonacci); + SaveChanges(); + + using (var numberSeriesNumberRepository = new NumberSeriesNumberRepository(this)) + { + var fibonacciNumbers = numberRepository.FindWhere(entity => fibonacciNumberSeriesValues.Contains(entity.Value)); + + foreach (var fibonacciNumber in fibonacciNumbers) + { + var fibonacciNumberSeriesNumber = new NumberSeriesNumber() + { + Identifier = Guid.NewGuid(), + NumberIdentifier = fibonacciNumber.Identifier, + NumberSeriesIdentifier = NumberSeries.Named.Fibonacci.Identifier + }; + + numberSeriesNumberRepository.Add(fibonacciNumberSeriesNumber); + } + + SaveChanges(); + } + } + } + + return this; + } + + /// + /// Configures the in-memory database to be used for this context. + /// + /// + /// Configuration information for the application. + /// + /// + /// A builder that is used to create or modify options for this context. + /// + protected sealed override void OnConfiguringInMemory(IConfiguration applicationConfiguration, InMemoryDbContextOptionsBuilder optionsBuilder) => base.OnConfiguringInMemory(applicationConfiguration, optionsBuilder); + + /// + /// Configures the SQL Server database to be used for this context. + /// + /// + /// Configuration information for the application. + /// + /// + /// A builder that is used to create or modify options for this context. + /// + protected sealed override void OnConfiguringSqlServer(IConfiguration applicationConfiguration, SqlServerDbContextOptionsBuilder optionsBuilder) => throw new InvalidOperationException(); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedRepositoryFactory.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedRepositoryFactory.cs new file mode 100644 index 00000000..41c15712 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedRepositoryFactory.cs @@ -0,0 +1,67 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using Microsoft.Extensions.Configuration; +using RapidField.SolidInstruments.DataAccess; +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests.Repositories; +using RapidField.SolidInstruments.ObjectComposition; +using System; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Encapsulates creation of new that map to Simulated database entities. + /// + public sealed class SimulatedRepositoryFactory : EntityFrameworkRepositoryFactory + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The database session that is used by the produced repositories. + /// + /// + /// is . + /// + public SimulatedRepositoryFactory(SimulatedContext context) + : base(context) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The database session that is used by the produced repositories. + /// + /// + /// Configuration information for the application. + /// + /// + /// is -or- is + /// . + /// + public SimulatedRepositoryFactory(SimulatedContext context, IConfiguration applicationConfiguration) + : base(context, applicationConfiguration) + { + return; + } + + /// + /// Configures the current . + /// + /// + /// Configuration information for the current . + /// + /// + /// The database session that is used by the produced repositories. + /// + protected override void Configure(ObjectFactoryConfiguration configuration, SimulatedContext context) => configuration.ProductionFunctions + .Add(() => new NumberRepository(context)) + .Add(() => new NumberSeriesNumberRepository(context)) + .Add(() => new NumberSeriesRepository(context)); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedSqlServerContext.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedSqlServerContext.cs new file mode 100644 index 00000000..88eed889 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedSqlServerContext.cs @@ -0,0 +1,55 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.Configuration; +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using System; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Represents a connection to a prototypical, SQL Server database. + /// + public sealed class SimulatedSqlServerContext : SimulatedContext + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Configuration information for the application. + /// + /// + /// is . + /// + public SimulatedSqlServerContext(IConfiguration applicationConfiguration) + : base(applicationConfiguration, ContextDatabaseType.SqlServer, QueryTrackingBehavior.TrackAll) + { + return; + } + + /// + /// Configures the in-memory database to be used for this context. + /// + /// + /// Configuration information for the application. + /// + /// + /// A builder that is used to create or modify options for this context. + /// + protected sealed override void OnConfiguringInMemory(IConfiguration applicationConfiguration, InMemoryDbContextOptionsBuilder optionsBuilder) => throw new InvalidOperationException(); + + /// + /// Configures the SQL Server database to be used for this context. + /// + /// + /// Configuration information for the application. + /// + /// + /// A builder that is used to create or modify options for this context. + /// + protected sealed override void OnConfiguringSqlServer(IConfiguration applicationConfiguration, SqlServerDbContextOptionsBuilder optionsBuilder) => base.OnConfiguringSqlServer(applicationConfiguration, optionsBuilder); + } +} \ No newline at end of file diff --git a/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedTransaction.cs b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedTransaction.cs new file mode 100644 index 00000000..0b7e9ee5 --- /dev/null +++ b/test/RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests/SimulatedTransaction.cs @@ -0,0 +1,56 @@ +// ================================================================================================================================= +// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ================================================================================================================================= + +using RapidField.SolidInstruments.DataAccess.EntityFramework; +using System; +using System.Data; + +namespace RapidField.SolidInstruments.DataAccess.EntityFramework.UnitTests +{ + /// + /// Represents a prototypical, in-memory database transaction. + /// + public sealed class SimulatedTransaction : EntityFrameworkTransaction + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The database session for the transaction. + /// + /// + /// has outstanding changes tracked against it. + /// + /// + /// is . + /// + public SimulatedTransaction(SimulatedContext context) + : base(context) + { + return; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The database session for the transaction. + /// + /// + /// The isolation level for the transaction, or to use the database default. The + /// default value is . + /// + /// + /// has outstanding changes tracked against it. + /// + /// + /// is . + /// + public SimulatedTransaction(SimulatedContext context, IsolationLevel isolationLevel) + : base(context, isolationLevel) + { + return; + } + } +} \ No newline at end of file