diff --git a/src/Conductors/RepositoryConductor.cs b/src/Conductors/RepositoryConductor.cs
index 9c7279d..98a9187 100644
--- a/src/Conductors/RepositoryConductor.cs
+++ b/src/Conductors/RepositoryConductor.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
+using System.Threading.Tasks;
using AndcultureCode.CSharp.Core;
using AndcultureCode.CSharp.Core.Extensions;
using AndcultureCode.CSharp.Core.Interfaces;
@@ -14,71 +15,9 @@ namespace AndcultureCode.CSharp.Conductors
/// Provides CRUD operations on a given repository
///
///
- public class RepositoryConductor : Conductor, IRepositoryConductor
+ public partial class RepositoryConductor : Conductor, IRepositoryConductor
where T : Entity
{
- #region Properties
-
- ///
- /// Ability to set and get the underlying repository's command timeout
- ///
- public int? CommandTimeout
- {
- get => _readConductor.CommandTimeout;
- set
- {
- _createConductor.CommandTimeout = value;
- _deleteConductor.CommandTimeout = value;
- _readConductor.CommandTimeout = value;
- _updateConductor.CommandTimeout = value;
- }
- }
-
- ///
- /// Conductor property to create an entity or entities
- ///
- protected readonly IRepositoryCreateConductor _createConductor;
-
- ///
- /// Conductor property to get an entity or entities
- ///
- protected readonly IRepositoryReadConductor _readConductor;
-
- ///
- /// Conductor property to update an entity or entities
- ///
- protected readonly IRepositoryUpdateConductor _updateConductor;
-
- ///
- /// Conductor property to delete an entity or entities
- ///
- protected readonly IRepositoryDeleteConductor _deleteConductor;
-
- #endregion Properties
-
- #region Constructor
-
- ///
- /// Constructor
- ///
- /// The conductor instance that should be used to perform create operations
- /// The conductor instance that should be used to perform read operations
- /// The conductor instance that should be used to perform update operations
- /// The conductor instance that should be used to perform delete operations
- public RepositoryConductor(
- IRepositoryCreateConductor createConductor,
- IRepositoryReadConductor readConductor,
- IRepositoryUpdateConductor updateConductor,
- IRepositoryDeleteConductor deleteConductor)
- {
- _createConductor = createConductor;
- _readConductor = readConductor;
- _updateConductor = updateConductor;
- _deleteConductor = deleteConductor;
- }
-
- #endregion Constructor
-
#region Public Methods
#region Create
@@ -88,7 +27,8 @@ public RepositoryConductor(
///
/// List of items to create
/// Id of user creating the items
- ///
+ /// A collection of the created items
+ [Obsolete("This method is deprecated in favor of its async counter part", false)]
public virtual IResult> BulkCreate(IEnumerable items, long? createdById = default(long?)) => _createConductor.BulkCreate(items, createdById);
///
diff --git a/src/Conductors/RepositoryConductorAsync.cs b/src/Conductors/RepositoryConductorAsync.cs
new file mode 100644
index 0000000..ce30201
--- /dev/null
+++ b/src/Conductors/RepositoryConductorAsync.cs
@@ -0,0 +1,78 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AndcultureCode.CSharp.Core.Interfaces;
+using AndcultureCode.CSharp.Core.Interfaces.Conductors;
+using AndcultureCode.CSharp.Core.Models.Entities;
+
+namespace AndcultureCode.CSharp.Conductors
+{
+ public partial class RepositoryConductor : Conductor, IRepositoryConductor
+ where T : Entity
+ {
+ #region Properties
+
+ ///
+ /// Ability to set and get the underlying repository's command timeout
+ ///
+ public int? CommandTimeout
+ {
+ get => _readConductor.CommandTimeout;
+ set
+ {
+ _createConductor.CommandTimeout = value;
+ _deleteConductor.CommandTimeout = value;
+ _readConductor.CommandTimeout = value;
+ _updateConductor.CommandTimeout = value;
+ }
+ }
+
+ ///
+ /// Conductor property to create an entity or entities
+ ///
+ protected readonly IRepositoryCreateConductor _createConductor;
+
+ ///
+ /// Conductor property to get an entity or entities
+ ///
+ protected readonly IRepositoryReadConductor _readConductor;
+
+ ///
+ /// Conductor property to update an entity or entities
+ ///
+ protected readonly IRepositoryUpdateConductor _updateConductor;
+
+ ///
+ /// Conductor property to delete an entity or entities
+ ///
+ protected readonly IRepositoryDeleteConductor _deleteConductor;
+
+ #endregion Properties
+
+ #region Constructor
+
+ ///
+ /// Constructor
+ ///
+ /// The conductor instance that should be used to perform create operations
+ /// The conductor instance that should be used to perform read operations
+ /// The conductor instance that should be used to perform update operations
+ /// The conductor instance that should be used to perform delete operations
+ public RepositoryConductor(
+ IRepositoryCreateConductor createConductor,
+ IRepositoryReadConductor readConductor,
+ IRepositoryUpdateConductor updateConductor,
+ IRepositoryDeleteConductor deleteConductor)
+ {
+ _createConductor = createConductor;
+ _readConductor = readConductor;
+ _updateConductor = updateConductor;
+ _deleteConductor = deleteConductor;
+ }
+
+ #endregion Constructor
+
+
+ public Task>> BulkCreateAsync(IEnumerable items, long? createdById = null) =>
+ _createConductor.BulkCreateAsync(items, createdById);
+ }
+}
diff --git a/src/Conductors/RepositoryCreateConductor.cs b/src/Conductors/RepositoryCreateConductor.cs
index 6488a1a..03deac9 100644
--- a/src/Conductors/RepositoryCreateConductor.cs
+++ b/src/Conductors/RepositoryCreateConductor.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using AndcultureCode.CSharp.Core.Interfaces;
using AndcultureCode.CSharp.Core.Interfaces.Conductors;
using AndcultureCode.CSharp.Core.Interfaces.Data;
@@ -11,47 +12,13 @@ namespace AndcultureCode.CSharp.Conductors
/// Ability to create an entity or multiple entities
///
///
- public class RepositoryCreateConductor : Conductor, IRepositoryCreateConductor
+ public partial class RepositoryCreateConductor : Conductor, IRepositoryCreateConductor
where T : class, IEntity
{
- #region Properties
-
- ///
- /// Ability to set and get the underlying DbContext's command timeout
- ///
- public int? CommandTimeout
- {
- get => _repository.CommandTimeout;
- set => _repository.CommandTimeout = value;
- }
-
- readonly IRepository _repository;
-
- #endregion
-
- #region Constructor
-
- ///
- /// Constructor
- ///
- ///
- public RepositoryCreateConductor(
- IRepository repository
- )
- {
- _repository = repository;
- }
-
- #endregion
#region IRepositoryCreateConductor
- ///
- /// Ability to create entities using a list in a single bulk operation.
- ///
- /// List of items to create
- /// Id of user creating the items
- ///
+ ///
public virtual IResult> BulkCreate(IEnumerable items, long? createdById = default(long?))
{
return _repository.BulkCreate(items, createdById);
diff --git a/src/Conductors/RepositoryCreateConductorAsync.cs b/src/Conductors/RepositoryCreateConductorAsync.cs
new file mode 100644
index 0000000..40c6417
--- /dev/null
+++ b/src/Conductors/RepositoryCreateConductorAsync.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AndcultureCode.CSharp.Core.Interfaces;
+using AndcultureCode.CSharp.Core.Interfaces.Conductors;
+using AndcultureCode.CSharp.Core.Interfaces.Data;
+using AndcultureCode.CSharp.Core.Interfaces.Entity;
+
+namespace AndcultureCode.CSharp.Conductors
+{
+ public partial class RepositoryCreateConductor : Conductor, IRepositoryCreateConductor
+ where T : class, IEntity
+ {
+ ///
+ /// Ability to set and get the underlying DbContext's command timeout
+ ///
+ public int? CommandTimeout
+ {
+ get => _repository.CommandTimeout;
+ set => _repository.CommandTimeout = value;
+ }
+
+ readonly IRepository _repository;
+
+
+ ///
+ /// Constructor
+ ///
+ ///
+ public RepositoryCreateConductor(
+ IRepository repository
+ )
+ {
+ _repository = repository;
+ }
+
+ ///
+ public virtual Task>> BulkCreateAsync(IEnumerable items, long? createdById = null)
+ {
+ if(items == null) throw new ArgumentNullException(nameof(items));
+ if(!items.Any()) throw new ArgumentException("An empty collection was provided", nameof(items));
+ return _repository.BulkCreateAsync(items, createdById);
+ }
+ }
+}
diff --git a/src/Core/Interfaces/Conductors/IRepositoryCreateConductor.cs b/src/Core/Interfaces/Conductors/IRepositoryCreateConductor.cs
index bab32a4..99268d4 100644
--- a/src/Core/Interfaces/Conductors/IRepositoryCreateConductor.cs
+++ b/src/Core/Interfaces/Conductors/IRepositoryCreateConductor.cs
@@ -4,7 +4,7 @@
namespace AndcultureCode.CSharp.Core.Interfaces.Conductors
{
- public interface IRepositoryCreateConductor
+ public partial interface IRepositoryCreateConductor
where T : class, IEntity
{
#region Properties
@@ -19,6 +19,13 @@ public interface IRepositoryCreateConductor
#region Methods
+ ///
+ /// Ability to create entities using a list in a single bulk operation.
+ ///
+ /// List of items to create
+ /// Id of user creating the items
+ ///
+ [Obsolete("This method is deprecated in favor of its async counter part", false)]
IResult> BulkCreate(IEnumerable items, long? createdById = null);
///
diff --git a/src/Core/Interfaces/Conductors/IRepositoryCreateConductorAsync.cs b/src/Core/Interfaces/Conductors/IRepositoryCreateConductorAsync.cs
new file mode 100644
index 0000000..fa2d21e
--- /dev/null
+++ b/src/Core/Interfaces/Conductors/IRepositoryCreateConductorAsync.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using AndcultureCode.CSharp.Core.Interfaces.Entity;
+
+namespace AndcultureCode.CSharp.Core.Interfaces.Conductors
+{
+ public partial interface IRepositoryCreateConductor
+ where T : class, IEntity
+ {
+ ///
+ /// Ability to asynchronously create entities using a list in a single bulk operation.
+ ///
+ /// List of items to create
+ /// Id of user creating the items
+ /// A collection of the created items
+ Task>> BulkCreateAsync(IEnumerable items, long? createdById = null);
+ }
+}
diff --git a/src/Core/Interfaces/Data/IRepository.cs b/src/Core/Interfaces/Data/IRepository.cs
index 9f196fb..c431ca9 100644
--- a/src/Core/Interfaces/Data/IRepository.cs
+++ b/src/Core/Interfaces/Data/IRepository.cs
@@ -10,7 +10,7 @@ namespace AndcultureCode.CSharp.Core.Interfaces.Data
///
///
///
- public interface IRepository
+ public partial interface IRepository
where T : class, IEntity
{
#region Properties
diff --git a/src/Core/Interfaces/Data/IRepositoryAsync.cs b/src/Core/Interfaces/Data/IRepositoryAsync.cs
new file mode 100644
index 0000000..4169d2b
--- /dev/null
+++ b/src/Core/Interfaces/Data/IRepositoryAsync.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AndcultureCode.CSharp.Core.Interfaces.Entity;
+
+namespace AndcultureCode.CSharp.Core.Interfaces.Data
+{
+ public partial interface IRepository
+ where T : class, IEntity
+ {
+ ///
+ /// Perform a DbContext.BulkInsert on an enumeration of T within a single transaction
+ ///
+ ///
+ ///
+ ///
+ Task>> BulkCreateAsync(IEnumerable items, long? createdById = null);
+
+ }
+}
diff --git a/test/Conductors.Tests/RepositoryConductorTests/BulkCreateAsyncShould.cs b/test/Conductors.Tests/RepositoryConductorTests/BulkCreateAsyncShould.cs
new file mode 100644
index 0000000..1263ec8
--- /dev/null
+++ b/test/Conductors.Tests/RepositoryConductorTests/BulkCreateAsyncShould.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+using System.Linq;
+using AndcultureCode.CSharp.Core.Interfaces.Conductors;
+using AndcultureCode.CSharp.Testing.Extensions;
+using AndcultureCode.CSharp.Testing.Tests;
+using Moq;
+using Shouldly;
+using Xunit;
+using Xunit.Abstractions;
+using System.Linq.Expressions;
+using System;
+using AndcultureCode.CSharp.Testing.Models.Stubs;
+using System.Threading.Tasks;
+
+namespace AndcultureCode.CSharp.Conductors.Tests.RepositoryConductorTests
+{
+ public class BulkCreateAsyncShould : ProjectUnitTest
+ {
+ #region Setup
+
+ public BulkCreateAsyncShould(ITestOutputHelper output) : base(output)
+ {
+ }
+
+ private IRepositoryConductor SetupSut(
+ IRepositoryMock repositoryMock
+ )
+ {
+ var repositoryCreateConductor = new RepositoryCreateConductor(repositoryMock.Object);
+ return new RepositoryConductor(
+ createConductor: repositoryCreateConductor,
+ deleteConductor: null,
+ readConductor: null,
+ updateConductor: null
+ );
+ }
+
+ #endregion Setup
+
+ [Fact]
+ public async Task Throw_Argument_Null_Exception_When_Given_Null_Input()
+ {
+ // Arrange
+ var repositoryMock = new IRepositoryMock();
+ var respositoryConductor = SetupSut(repositoryMock);
+
+ // Act & Assert
+ await Assert.ThrowsAsync(() => respositoryConductor.BulkCreateAsync(null));
+ }
+
+ [Fact]
+ public async Task Throw_Argument_Exception_When_Given_Empty_Input()
+ {
+ // Arrange
+ var repositoryMock = new IRepositoryMock();
+ var respositoryConductor = SetupSut(repositoryMock);
+
+ // Act & Assert
+ await Assert.ThrowsAsync(() => respositoryConductor.BulkCreateAsync(new List()));
+ }
+
+ }
+}
diff --git a/test/Conductors.Tests/RepositoryConductorTests/IRepositoryMock.cs b/test/Conductors.Tests/RepositoryConductorTests/IRepositoryMock.cs
new file mode 100644
index 0000000..a26c13f
--- /dev/null
+++ b/test/Conductors.Tests/RepositoryConductorTests/IRepositoryMock.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AndcultureCode.CSharp.Core.Interfaces;
+using AndcultureCode.CSharp.Core.Interfaces.Conductors;
+using AndcultureCode.CSharp.Core.Interfaces.Data;
+using AndcultureCode.CSharp.Core.Interfaces.Entity;
+using Moq;
+
+namespace AndcultureCode.CSharp.Conductors.Tests.RepositoryConductorTests
+{
+
+
+ internal sealed class IRepositoryMock : Mock>
+ where T : class, IEntity
+ {
+ public IRepositoryMock BulkCreateAsync(IResult> output, Action callback)
+ {
+ Setup(x => x.BulkCreateAsync(It.IsAny>(), null))
+ .Returns(Task.FromResult(output));
+ return this;
+ }
+ }
+}