diff --git a/src/Services/Ordering/Ordering.Application/Commands/CancelOrderRequest.cs b/src/Services/Ordering/Ordering.Application/Commands/CancelOrderRequest.cs deleted file mode 100644 index b68dbd375..000000000 --- a/src/Services/Ordering/Ordering.Application/Commands/CancelOrderRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands -{ - using MediatR; - - public class CancelOrderRequest - : IAsyncRequest - { - public int OrderId { get; private set; } - - public CancelOrderRequest(int orderId) - { - OrderId = orderId; - } - } -} diff --git a/src/Services/Ordering/Ordering.Application/Commands/CancelOrderRequestHandler.cs b/src/Services/Ordering/Ordering.Application/Commands/CancelOrderRequestHandler.cs deleted file mode 100644 index 4874c178f..000000000 --- a/src/Services/Ordering/Ordering.Application/Commands/CancelOrderRequestHandler.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands -{ - using MediatR; - using System; - using System.Threading.Tasks; - - public class CancelOrderRequestHandler - : IAsyncRequestHandler - { - public Task Handle(CancelOrderRequest message) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Services/Ordering/Ordering.Application/Commands/NewOrderREquestHandler.cs b/src/Services/Ordering/Ordering.Application/Commands/NewOrderREquestHandler.cs index 466f42ac6..2f321a685 100644 --- a/src/Services/Ordering/Ordering.Application/Commands/NewOrderREquestHandler.cs +++ b/src/Services/Ordering/Ordering.Application/Commands/NewOrderREquestHandler.cs @@ -1,15 +1,110 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands { + using Domain.Repositories; using MediatR; + using System.Linq; using System; using System.Threading.Tasks; + using Domain; public class NewOrderRequestHandler : IAsyncRequestHandler { - public Task Handle(NewOrderRequest message) + private readonly IBuyerRepository _buyerRepository; + private readonly IOrderRepository _orderRepository; + + public NewOrderRequestHandler(IBuyerRepository buyerRepository,IOrderRepository orderRepository) + { + if (buyerRepository == null) + { + throw new ArgumentNullException(nameof(buyerRepository)); + } + + if (orderRepository == null) + { + throw new ArgumentNullException(nameof(orderRepository)); + } + + _buyerRepository = buyerRepository; + _orderRepository = orderRepository; + } + public async Task Handle(NewOrderRequest message) + { + //find buyer/payment or add a new one + + var buyer = await _buyerRepository.FindAsync(message.Buyer); + + if (buyer == null) + { + buyer = CreateBuyer(message); + } + + var payment = GetExistingPaymentOrAddANewOne(buyer, message); + + await _buyerRepository.UnitOfWork.SaveChangesAsync(); + + //create order + var order = CreateOrder(buyer.Id, payment.Id, 0); + order.SetAddress( new Address() + { + City = message.City, + State = message.State, + Street = message.Street, + ZipCode = message.ZipCode + }); + + _orderRepository.Add(order); + + var result = await _orderRepository.UnitOfWork.SaveChangesAsync(); + + return result > 0; + } + + + + Payment GetExistingPaymentOrAddANewOne(Buyer buyer, NewOrderRequest message) + { + Payment payment = PaymentAlreadyExist(buyer, message); + + if (payment == null) + { + payment = CreatePayment(message); + buyer.Payments.Add(payment); + } + + return payment; + + } + + Payment PaymentAlreadyExist(Domain.Buyer buyer, NewOrderRequest message) + { + return buyer.Payments + .SingleOrDefault(p => + { + return p.CardHolderName == message.CardHolderName + && + p.CardNumber == message.CardNumber + && + p.Expiration == message.CardExpiration + && + p.SecurityNumber == message.CardSecurityNumber; + }); + } + + Buyer CreateBuyer(NewOrderRequest message) + { + return _buyerRepository.Add( + new Buyer(message.Buyer)); + } + + Order CreateOrder(int buyerId, int paymentId, int addressId) + { + return new Order(buyerId, paymentId); + } + + Payment CreatePayment(NewOrderRequest message) { - throw new NotImplementedException(); + return new Payment(message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration, message.CardTypeId); } } } diff --git a/src/Services/Ordering/Ordering.Application/Commands/NewOrderRequest.cs b/src/Services/Ordering/Ordering.Application/Commands/NewOrderRequest.cs index 4dd5ac5bc..108a4d98e 100644 --- a/src/Services/Ordering/Ordering.Application/Commands/NewOrderRequest.cs +++ b/src/Services/Ordering/Ordering.Application/Commands/NewOrderRequest.cs @@ -1,10 +1,33 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Commands { + using System; using MediatR; public class NewOrderRequest :IAsyncRequest { + public string City { get; set; } + + public string Street { get; set; } + + public string State { get; set; } + + public string Country { get; set; } + + public string ZipCode { get; set; } + + public string CardNumber { get; set; } + + public string CardHolderName { get; set; } + + public DateTime CardExpiration { get; set; } + + public string CardSecurityNumber { get; set; } + + public int CardTypeId { get; set; } + + public string Buyer { get; set; } + public NewOrderRequest() { } diff --git a/src/Services/Ordering/Ordering.Application/Decorators/LogDecorator.cs b/src/Services/Ordering/Ordering.Application/Decorators/LogDecorator.cs new file mode 100644 index 000000000..bc095a81e --- /dev/null +++ b/src/Services/Ordering/Ordering.Application/Decorators/LogDecorator.cs @@ -0,0 +1,34 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.Application.Decorators +{ + using Extensions.Logging; + using MediatR; + using System.Threading.Tasks; + + public class LogDecorator + : IAsyncRequestHandler + where TRequest : IAsyncRequest + { + private readonly IAsyncRequestHandler _inner; + private readonly ILogger> _logger; + + + public LogDecorator( + IAsyncRequestHandler inner, + ILogger> logger) + { + _inner = inner; + _logger = logger; + } + + public async Task Handle(TRequest message) + { + _logger.LogInformation($"Executing command {_inner.GetType().FullName}"); + + var response = await _inner.Handle(message); + + _logger.LogInformation($"Succedded executed command {_inner.GetType().FullName}"); + + return response; + } + } +} diff --git a/src/Services/Ordering/Ordering.Application/Queries/IOrderQueries.cs b/src/Services/Ordering/Ordering.Application/Queries/IOrderQueries.cs index 6b364a569..a011f2359 100644 --- a/src/Services/Ordering/Ordering.Application/Queries/IOrderQueries.cs +++ b/src/Services/Ordering/Ordering.Application/Queries/IOrderQueries.cs @@ -6,6 +6,8 @@ { Task GetOrder(int id); - Task GetPendingOrders(); + Task GetOrders(); + + Task GetCardTypes(); } } diff --git a/src/Services/Ordering/Ordering.Application/Queries/OrderQueries.cs b/src/Services/Ordering/Ordering.Application/Queries/OrderQueries.cs index 0ab74090a..97283546e 100644 --- a/src/Services/Ordering/Ordering.Application/Queries/OrderQueries.cs +++ b/src/Services/Ordering/Ordering.Application/Queries/OrderQueries.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration; using System.Data.SqlClient; using System.Threading.Tasks; + using System; public class OrderQueries :IOrderQueries @@ -15,6 +16,7 @@ _connectionString = configuration["ConnectionString"]; } + public async Task GetOrder(int id) { using (var connection = new SqlConnection(_connectionString)) @@ -25,14 +27,29 @@ } } - public async Task GetPendingOrders() + public async Task GetOrders() { using (var connection = new SqlConnection(_connectionString)) { connection.Open(); - return await connection.QueryAsync("SELECT * FROM ordering.Orders"); + return await connection.QueryAsync(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status],SUM(oi.units*oi.unitprice) as total + FROM [ordering].[Orders] o + LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid + LEFT JOIN[ordering].[orderstatus] os on o.StatusId = os.Id + GROUP BY o.[Id], o.[OrderDate], os.[Name]"); } } + + public async Task GetCardTypes() + { + using (var connection = new SqlConnection(_connectionString)) + { + connection.Open(); + + return await connection.QueryAsync("SELECT * FROM ordering.cardtypes"); + } + } + } } diff --git a/src/Services/Ordering/Ordering.Application/project.json b/src/Services/Ordering/Ordering.Application/project.json index c6531feaf..158ae13d8 100644 --- a/src/Services/Ordering/Ordering.Application/project.json +++ b/src/Services/Ordering/Ordering.Application/project.json @@ -8,7 +8,9 @@ "System.Dynamic.Runtime": "4.0.11", "Microsoft.CSharp": "4.0.1", "Microsoft.Extensions.Configuration": "1.0.0", - "System.Data.SqlClient": "4.1.0" + "System.Data.SqlClient": "4.1.0", + "Microsoft.Extensions.Logging.Abstractions": "1.0.0", + "Ordering.Domain": "1.0.0-*" }, "frameworks": { diff --git a/src/Services/Ordering/Ordering.Domain/Address.cs b/src/Services/Ordering/Ordering.Domain/Address.cs index 19e62d9ca..154becb2c 100644 --- a/src/Services/Ordering/Ordering.Domain/Address.cs +++ b/src/Services/Ordering/Ordering.Domain/Address.cs @@ -6,24 +6,15 @@ public class Address : Entity { - public String Street { get; private set; } + public String Street { get; set; } - public String City { get; private set; } + public String City { get; set; } - public String State { get; private set; } + public String State { get; set; } - public String StateCode { get; private set; } + public String Country { get; set; } - public String Country { get; private set; } + public String ZipCode { get; set; } - public String CountryCode { get; private set; } - - public String ZipCode { get; private set; } - - public double Latitude { get; private set; } - - public double Longitude { get; private set; } - - protected Address() { } } } diff --git a/src/Services/Ordering/Ordering.Domain/Buyer.cs b/src/Services/Ordering/Ordering.Domain/Buyer.cs index 40bb11499..58634f342 100644 --- a/src/Services/Ordering/Ordering.Domain/Buyer.cs +++ b/src/Services/Ordering/Ordering.Domain/Buyer.cs @@ -1,12 +1,27 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain { using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; + using System; + using System.Collections.Generic; public class Buyer :Entity,IAggregateRoot { public string FullName { get; private set; } + public HashSet Payments { get; private set; } + protected Buyer() { } + + public Buyer(string fullName) + { + if (String.IsNullOrWhiteSpace(fullName)) + { + throw new ArgumentNullException(nameof(fullName)); + } + + this.FullName = fullName; + this.Payments = new HashSet(); + } } } diff --git a/src/Services/Ordering/Ordering.Domain/CardType.cs b/src/Services/Ordering/Ordering.Domain/CardType.cs index ca875321c..b05357292 100644 --- a/src/Services/Ordering/Ordering.Domain/CardType.cs +++ b/src/Services/Ordering/Ordering.Domain/CardType.cs @@ -11,8 +11,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain : Entity { public static CardType Amex = new CardType(1, "Amex"); - public static CardType Visa = new CardType(1, "Visa"); - public static CardType MasterCard = new CardType(1, "MasterCard"); + public static CardType Visa = new CardType(2, "Visa"); + public static CardType MasterCard = new CardType(3, "MasterCard"); public string Name { get; private set; } diff --git a/src/Services/Ordering/Ordering.Domain/Order.cs b/src/Services/Ordering/Ordering.Domain/Order.cs index e7bbefce5..2e6ee3cbd 100644 --- a/src/Services/Ordering/Ordering.Domain/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/Order.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; public class Order - :Entity, IAggregateRoot + : Entity, IAggregateRoot { public int BuyerId { get; private set; } @@ -23,14 +23,28 @@ public Address ShippingAddress { get; private set; } - public int? BillingAddressId { get; private set; } - - public Address BillingAddress { get; private set; } - public int PaymentId { get; private set; } public Payment Payment { get; private set; } protected Order() { } + + public Order(int buyerId, int paymentId) + { + BuyerId = buyerId; + PaymentId = paymentId; + StatusId = OrderStatus.InProcess.Id; + OrderDate = DateTime.UtcNow; + } + + public void SetAddress(Address address) + { + if (address == null) + { + throw new ArgumentNullException(nameof(address)); + } + + ShippingAddress = address; + } } } diff --git a/src/Services/Ordering/Ordering.Domain/OrderStatus.cs b/src/Services/Ordering/Ordering.Domain/OrderStatus.cs index 8a9faa511..e337da6f7 100644 --- a/src/Services/Ordering/Ordering.Domain/OrderStatus.cs +++ b/src/Services/Ordering/Ordering.Domain/OrderStatus.cs @@ -10,11 +10,9 @@ { public string Name { get; private set; } - public static OrderStatus New = new OrderStatus(1, nameof(New).ToLowerInvariant()); - public static OrderStatus Submitted = new OrderStatus(1, nameof(Submitted).ToLowerInvariant()); public static OrderStatus InProcess = new OrderStatus(1, nameof(InProcess).ToLowerInvariant()); - public static OrderStatus Shipped = new OrderStatus(1, nameof(Shipped).ToLowerInvariant()); - public static OrderStatus Canceled = new OrderStatus(1, nameof(Canceled).ToLowerInvariant()); + public static OrderStatus Shipped = new OrderStatus(2, nameof(Shipped).ToLowerInvariant()); + public static OrderStatus Canceled = new OrderStatus(3, nameof(Canceled).ToLowerInvariant()); protected OrderStatus() { @@ -28,7 +26,7 @@ public static IEnumerable List() { - return new[] { New, Submitted, InProcess, Shipped, Canceled }; + return new[] { InProcess, Shipped, Canceled }; } public static OrderStatus FromName(string name) diff --git a/src/Services/Ordering/Ordering.Domain/Payment.cs b/src/Services/Ordering/Ordering.Domain/Payment.cs index ccf35e133..546b3482f 100644 --- a/src/Services/Ordering/Ordering.Domain/Payment.cs +++ b/src/Services/Ordering/Ordering.Domain/Payment.cs @@ -2,14 +2,13 @@ { using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; public class Payment - : Entity, IAggregateRoot + : Entity { + public int BuyerId { get; private set; } + public string CardNumber { get; private set; } public string SecurityNumber { get; private set; } @@ -23,5 +22,34 @@ public DateTime Expiration { get; private set; } protected Payment() { } + + public Payment(string cardNumber, string securityNumber, string cardHolderName, DateTime expiration, int cardTypeId) + { + if (String.IsNullOrWhiteSpace(cardNumber)) + { + throw new ArgumentException(nameof(cardNumber)); + } + + if (String.IsNullOrWhiteSpace(securityNumber)) + { + throw new ArgumentException(nameof(securityNumber)); + } + + if (String.IsNullOrWhiteSpace(cardHolderName)) + { + throw new ArgumentException(nameof(cardHolderName)); + } + + if (expiration < DateTime.UtcNow) + { + throw new ArgumentException(nameof(expiration)); + } + + this.CardNumber = cardNumber; + this.SecurityNumber = securityNumber; + this.CardHolderName = cardHolderName; + this.Expiration = expiration; + this.CardTypeId = cardTypeId; + } } } diff --git a/src/Services/Ordering/Ordering.Domain/Repositories/IBuyerRepository.cs b/src/Services/Ordering/Ordering.Domain/Repositories/IBuyerRepository.cs new file mode 100644 index 000000000..5e41b7af6 --- /dev/null +++ b/src/Services/Ordering/Ordering.Domain/Repositories/IBuyerRepository.cs @@ -0,0 +1,13 @@ +using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Repositories +{ + public interface IBuyerRepository + :IRepository + { + Buyer Add(Buyer buyer); + + Task FindAsync(string name); + } +} diff --git a/src/Services/Ordering/Ordering.Domain/Repositories/IOrderRepository.cs b/src/Services/Ordering/Ordering.Domain/Repositories/IOrderRepository.cs new file mode 100644 index 000000000..0648b00c5 --- /dev/null +++ b/src/Services/Ordering/Ordering.Domain/Repositories/IOrderRepository.cs @@ -0,0 +1,10 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Repositories +{ + using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; + + public interface IOrderRepository + :IRepository + { + Order Add(Order order); + } +} diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs index 802273f1f..fdbc61e79 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs @@ -1,10 +1,11 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork { public interface IUnitOfWork : IDisposable { - Task CommitAsync(); + Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs index d766bd6d0..9be6d29d5 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs @@ -1,11 +1,15 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure { + using System; + using System.Threading.Tasks; + using Domain.SeedWork; + using EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.eShopOnContainers.Services.Ordering.Domain; public class OrderingContext - : DbContext + : DbContext,IUnitOfWork { const string DEFAULT_SCHEMA = "ordering"; @@ -18,7 +22,7 @@ public DbSet Buyers { get; set; } - public DbSet Cards { get; set; } + public DbSet CardTypes { get; set; } public DbSet OrderStatus { get; set; } @@ -32,21 +36,23 @@ modelBuilder.Entity(ConfigurePayment); modelBuilder.Entity(ConfigureOrder); modelBuilder.Entity(ConfigureOrderItems); - - modelBuilder.Entity() - .ToTable("orderstatus", DEFAULT_SCHEMA); - - modelBuilder.Entity() - .ToTable("cardtypes", DEFAULT_SCHEMA); + modelBuilder.Entity(ConfigureCardTypes); + modelBuilder.Entity(ConfigureOrderStatus); + modelBuilder.Entity
(ConfigureAddress); modelBuilder.Entity
() .ToTable("address", DEFAULT_SCHEMA); } + + void ConfigureBuyer(EntityTypeBuilder buyerConfiguration) { buyerConfiguration.ToTable("buyers", DEFAULT_SCHEMA); + buyerConfiguration.HasIndex(b => b.FullName) + .IsUnique(true); + buyerConfiguration.HasKey(b => b.Id); buyerConfiguration.Property(b => b.Id) @@ -55,6 +61,11 @@ buyerConfiguration.Property(b => b.FullName) .HasMaxLength(200) .IsRequired(); + + buyerConfiguration.HasMany(b => b.Payments) + .WithOne() + .HasForeignKey(p => p.BuyerId) + .OnDelete(DeleteBehavior.Cascade); } void ConfigurePayment(EntityTypeBuilder paymentConfiguration) @@ -96,12 +107,8 @@ orderConfiguration.HasOne(o => o.Payment) .WithMany() - .HasForeignKey(o => o.PaymentId); - - orderConfiguration.HasOne(o => o.BillingAddress) - .WithMany() - .HasForeignKey(o => o.BillingAddressId) - .OnDelete(EntityFrameworkCore.Metadata.DeleteBehavior.SetNull); + .HasForeignKey(o => o.PaymentId) + .OnDelete(DeleteBehavior.Restrict); orderConfiguration.HasOne(o => o.Buyer) .WithMany() @@ -134,5 +141,40 @@ .ForSqlServerHasDefaultValue(1) .IsRequired(); } + + void ConfigureOrderStatus(EntityTypeBuilder orderStatusConfiguration) + { + orderStatusConfiguration.ToTable("orderstatus", DEFAULT_SCHEMA); + + orderStatusConfiguration.HasKey(o => o.Id); + + orderStatusConfiguration.Property(o => o.Id) + .HasDefaultValue(1) + .IsRequired(); + + orderStatusConfiguration.Property(o => o.Name) + .HasMaxLength(200) + .IsRequired(); + } + + void ConfigureCardTypes(EntityTypeBuilder cardTypesConfiguration) + { + cardTypesConfiguration.ToTable("cardtypes", DEFAULT_SCHEMA); + + cardTypesConfiguration.HasKey(ct => ct.Id); + + cardTypesConfiguration.Property(ct => ct.Id) + .HasDefaultValue(1) + .IsRequired(); + + cardTypesConfiguration.Property(ct => ct.Name) + .HasMaxLength(200) + .IsRequired(); + } + + void ConfigureAddress(EntityTypeBuilder
addressConfiguration) + { + addressConfiguration.ToTable("address", DEFAULT_SCHEMA); + } } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs b/src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs new file mode 100644 index 000000000..3a1f75c0d --- /dev/null +++ b/src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs @@ -0,0 +1,51 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories +{ + using Domain.SeedWork; + using Microsoft.EntityFrameworkCore; + using Microsoft.eShopOnContainers.Services.Ordering.Domain; + using Microsoft.eShopOnContainers.Services.Ordering.Domain.Repositories; + using System; + using System.Linq; + using System.Threading.Tasks; + + public class BuyerRepository + : IBuyerRepository + { + private readonly OrderingContext _context; + + public BuyerRepository(OrderingContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + _context = context; + } + + public IUnitOfWork UnitOfWork + { + get + { + return _context; + } + } + + public Buyer Add(Buyer buyer) + { + return _context.Buyers + .Add(buyer) + .Entity; + } + + public async Task FindAsync(string name) + { + var buyer = await _context.Buyers + .Include(b => b.Payments) + .Where(b => b.FullName == name) + .SingleOrDefaultAsync(); + + return buyer; + } + } +} diff --git a/src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs b/src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs new file mode 100644 index 000000000..94f48d9aa --- /dev/null +++ b/src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs @@ -0,0 +1,36 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories +{ + using Domain; + using Domain.SeedWork; + using Microsoft.eShopOnContainers.Services.Ordering.Domain.Repositories; + using System; + + public class OrderRepository + : IOrderRepository + { + private readonly OrderingContext _context; + public IUnitOfWork UnitOfWork + { + get + { + return _context; + } + } + + public OrderRepository(OrderingContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + _context = context; + } + + public Order Add(Order order) + { + return _context.Orders.Add(order) + .Entity; + } + } +}