Added OrderItem features and moved queries to the OrderingQueries class
This commit is contained in:
parent
1ba7087965
commit
68bcb70fd2
@ -15,19 +15,16 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
|
||||
[Route("api/[controller]")]
|
||||
public class OrderingController : Controller
|
||||
{
|
||||
private OrderingDbContext _context;
|
||||
private IOrderRepository _orderRepository;
|
||||
private OrderingQueries _queries;
|
||||
|
||||
public OrderingController(IOrderRepository orderRepository,
|
||||
OrderingQueries orderingQueries,
|
||||
OrderingDbContext context)
|
||||
OrderingQueries orderingQueries
|
||||
)
|
||||
{
|
||||
//Injected objects from the IoC container
|
||||
_orderRepository = orderRepository;
|
||||
_queries = orderingQueries;
|
||||
|
||||
_context = context;
|
||||
}
|
||||
|
||||
|
||||
@ -42,28 +39,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
|
||||
|
||||
// GET api/ordering/orders/xxxGUIDxxxx
|
||||
[HttpGet("orders/{orderId:Guid}")]
|
||||
public async Task<IActionResult> GetOrderByGuid(Guid orderId)
|
||||
public async Task<IActionResult> GetOrderById(Guid orderId)
|
||||
{
|
||||
//var order = await _orderRepository.Get(orderId);
|
||||
|
||||
var order = await _context.Orders
|
||||
.Include(o => o.ShippingAddress)
|
||||
.Include(o => o.BillingAddress)
|
||||
.Where(o => o.Id == orderId)
|
||||
.SingleOrDefaultAsync<Order>();
|
||||
|
||||
// Dynamically generated a Response-Model that includes only the fields you need in the response.
|
||||
// This keeps the JSON response minimal.
|
||||
// Could also use var
|
||||
dynamic response = new
|
||||
{
|
||||
id = order.Id,
|
||||
orderDate = order.OrderDate,
|
||||
shippingAddress = order.ShippingAddress,
|
||||
billingAddress = order.BillingAddress,
|
||||
//items = order.Items.Select(i => i.Content)
|
||||
};
|
||||
|
||||
dynamic response = await _queries.GetOrderById(orderId);
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
|
89
src/Services/Ordering/Ordering.API/Migrations/20160913052800_Migration4.Designer.cs
generated
Normal file
89
src/Services/Ordering/Ordering.API/Migrations/20160913052800_Migration4.Designer.cs
generated
Normal file
@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.SqlData.UnitOfWork;
|
||||
|
||||
namespace Ordering.API.Migrations
|
||||
{
|
||||
[DbContext(typeof(OrderingDbContext))]
|
||||
[Migration("20160913052800_Migration4")]
|
||||
partial class Migration4
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
|
||||
.HasAnnotation("Relational:Sequence:shared.OrderSequences", "'OrderSequences', 'shared', '1001', '1', '', '', 'Int32', 'False'")
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("City");
|
||||
|
||||
b.Property<string>("Country");
|
||||
|
||||
b.Property<string>("CountryCode");
|
||||
|
||||
b.Property<double>("Latitude");
|
||||
|
||||
b.Property<double>("Longitude");
|
||||
|
||||
b.Property<string>("State");
|
||||
|
||||
b.Property<string>("StateCode");
|
||||
|
||||
b.Property<string>("Street");
|
||||
|
||||
b.Property<string>("ZipCode");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<Guid?>("BillingAddressId");
|
||||
|
||||
b.Property<Guid>("BuyerId");
|
||||
|
||||
b.Property<DateTime>("OrderDate");
|
||||
|
||||
b.Property<int>("SequenceNumber")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("NEXT VALUE FOR shared.OrderSequences");
|
||||
|
||||
b.Property<Guid?>("ShippingAddressId");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BillingAddressId");
|
||||
|
||||
b.HasIndex("ShippingAddressId");
|
||||
|
||||
b.ToTable("Orders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", "BillingAddress")
|
||||
.WithMany()
|
||||
.HasForeignKey("BillingAddressId");
|
||||
|
||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", "ShippingAddress")
|
||||
.WithMany()
|
||||
.HasForeignKey("ShippingAddressId");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Ordering.API.Migrations
|
||||
{
|
||||
public partial class Migration4 : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: "shared");
|
||||
|
||||
migrationBuilder.CreateSequence<int>(
|
||||
name: "OrderSequences",
|
||||
schema: "shared",
|
||||
startValue: 1001L);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "SequenceNumber",
|
||||
table: "Orders",
|
||||
nullable: false,
|
||||
defaultValueSql: "NEXT VALUE FOR shared.OrderSequences");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropSequence(
|
||||
name: "OrderSequences",
|
||||
schema: "shared");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SequenceNumber",
|
||||
table: "Orders");
|
||||
}
|
||||
}
|
||||
}
|
121
src/Services/Ordering/Ordering.API/Migrations/20160913061710_Migration5.Designer.cs
generated
Normal file
121
src/Services/Ordering/Ordering.API/Migrations/20160913061710_Migration5.Designer.cs
generated
Normal file
@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.SqlData.UnitOfWork;
|
||||
|
||||
namespace Ordering.API.Migrations
|
||||
{
|
||||
[DbContext(typeof(OrderingDbContext))]
|
||||
[Migration("20160913061710_Migration5")]
|
||||
partial class Migration5
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
|
||||
.HasAnnotation("Relational:Sequence:shared.OrderSequences", "'OrderSequences', 'shared', '1001', '1', '', '', 'Int32', 'False'")
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("City");
|
||||
|
||||
b.Property<string>("Country");
|
||||
|
||||
b.Property<string>("CountryCode");
|
||||
|
||||
b.Property<double>("Latitude");
|
||||
|
||||
b.Property<double>("Longitude");
|
||||
|
||||
b.Property<string>("State");
|
||||
|
||||
b.Property<string>("StateCode");
|
||||
|
||||
b.Property<string>("Street");
|
||||
|
||||
b.Property<string>("ZipCode");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<Guid?>("BillingAddressId");
|
||||
|
||||
b.Property<Guid>("BuyerId");
|
||||
|
||||
b.Property<DateTime>("OrderDate");
|
||||
|
||||
b.Property<int>("SequenceNumber")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("NEXT VALUE FOR shared.OrderSequences");
|
||||
|
||||
b.Property<Guid?>("ShippingAddressId");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BillingAddressId");
|
||||
|
||||
b.HasIndex("ShippingAddressId");
|
||||
|
||||
b.ToTable("Orders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<decimal>("Discount");
|
||||
|
||||
b.Property<int>("FulfillmentRemaining");
|
||||
|
||||
b.Property<Guid>("OrderId");
|
||||
|
||||
b.Property<Guid>("ProductId");
|
||||
|
||||
b.Property<int>("Quantity");
|
||||
|
||||
b.Property<decimal>("UnitPrice");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OrderId");
|
||||
|
||||
b.ToTable("OrderItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", "BillingAddress")
|
||||
.WithMany()
|
||||
.HasForeignKey("BillingAddressId");
|
||||
|
||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", "ShippingAddress")
|
||||
.WithMany()
|
||||
.HasForeignKey("ShippingAddressId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderItem", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order")
|
||||
.WithMany("OrderItems")
|
||||
.HasForeignKey("OrderId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Ordering.API.Migrations
|
||||
{
|
||||
public partial class Migration5 : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OrderItem",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(nullable: false),
|
||||
Discount = table.Column<decimal>(nullable: false),
|
||||
FulfillmentRemaining = table.Column<int>(nullable: false),
|
||||
OrderId = table.Column<Guid>(nullable: false),
|
||||
ProductId = table.Column<Guid>(nullable: false),
|
||||
Quantity = table.Column<int>(nullable: false),
|
||||
UnitPrice = table.Column<decimal>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OrderItem", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OrderItem_Orders_OrderId",
|
||||
column: x => x.OrderId,
|
||||
principalTable: "Orders",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OrderItem_OrderId",
|
||||
table: "OrderItem",
|
||||
column: "OrderId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "OrderItem");
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ namespace Ordering.API.Migrations
|
||||
{
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
|
||||
.HasAnnotation("Relational:Sequence:shared.OrderSequences", "'OrderSequences', 'shared', '1001', '1', '', '', 'Int32', 'False'")
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", b =>
|
||||
@ -55,6 +56,10 @@ namespace Ordering.API.Migrations
|
||||
|
||||
b.Property<DateTime>("OrderDate");
|
||||
|
||||
b.Property<int>("SequenceNumber")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("NEXT VALUE FOR shared.OrderSequences");
|
||||
|
||||
b.Property<Guid?>("ShippingAddressId");
|
||||
|
||||
b.Property<int>("Status");
|
||||
@ -68,6 +73,30 @@ namespace Ordering.API.Migrations
|
||||
b.ToTable("Orders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<decimal>("Discount");
|
||||
|
||||
b.Property<int>("FulfillmentRemaining");
|
||||
|
||||
b.Property<Guid>("OrderId");
|
||||
|
||||
b.Property<Guid>("ProductId");
|
||||
|
||||
b.Property<int>("Quantity");
|
||||
|
||||
b.Property<decimal>("UnitPrice");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OrderId");
|
||||
|
||||
b.ToTable("OrderItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Address", "BillingAddress")
|
||||
@ -78,6 +107,14 @@ namespace Ordering.API.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("ShippingAddressId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderItem", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order")
|
||||
.WithMany("OrderItems")
|
||||
.HasForeignKey("OrderId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
|
||||
|
||||
//Add EF Core Context (UnitOfWork)
|
||||
var connection = @"Server=(localdb)\mssqllocaldb;Database=Microsoft.eShopOnContainers.Services.OrderingDb;Trusted_Connection=True;";
|
||||
services.AddDbContext<OrderingDbContext>(options => options.UseSqlServer(connection));
|
||||
services.AddDbContext<OrderingDbContext>(options => options.UseSqlServer(connection)
|
||||
.UseSqlServer(connection, b => b.MigrationsAssembly("Ordering.API"))
|
||||
//(CDLTLL) MigrationsAssembly will be Ordering.SqlData, but when supported
|
||||
//Standard Library 1.6 by "Microsoft.EntityFrameworkCore.Tools"
|
||||
//Version "1.0.0-preview2-final" just supports .NET Core
|
||||
);
|
||||
|
||||
services.AddTransient<IOrderRepository, OrderRepository>();
|
||||
services.AddTransient<OrderingQueries, OrderingQueries>();
|
||||
|
@ -20,6 +20,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel
|
||||
this.ShippingAddress = shippingAddress;
|
||||
this.BillingAddress = billingAddress;
|
||||
this.OrderDate = orderDate;
|
||||
|
||||
this.Status = OrderStatus.New;
|
||||
}
|
||||
|
||||
//Infrastructure requisite - Parameterless constructor needed by EF
|
||||
@ -27,22 +29,32 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel
|
||||
|
||||
//Order ID comes derived from the Entity base class
|
||||
|
||||
//List<OrderItem> _orderItems;
|
||||
//public virtual List<OrderItem> orderItems
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// if (_orderItems == null)
|
||||
// _orderItems = new List<OrderItem>();
|
||||
List<OrderItem> _orderItems;
|
||||
public virtual List<OrderItem> OrderItems
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_orderItems == null)
|
||||
_orderItems = new List<OrderItem>();
|
||||
|
||||
// return _orderItems;
|
||||
// }
|
||||
return _orderItems;
|
||||
}
|
||||
|
||||
// private set
|
||||
// {
|
||||
// _orderItems = value;
|
||||
// }
|
||||
//}
|
||||
private set
|
||||
{
|
||||
_orderItems = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string OrderNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("{0}/{1}-{2}", OrderDate.Year, OrderDate.Month, SequenceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
public int SequenceNumber { get; set; }
|
||||
|
||||
public virtual Guid BuyerId { get; private set; }
|
||||
|
||||
@ -54,5 +66,47 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel
|
||||
|
||||
public virtual OrderStatus Status { get; private set; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Domain Rules and Logic in Order Aggregate-Root (Sample of a "NO ANEMIC DOMAIN MODEL" )
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public OrderItem AddNewOrderItem(Guid productId, int quantity, decimal unitPrice, decimal discount)
|
||||
{
|
||||
//check preconditions
|
||||
if (productId == Guid.Empty)
|
||||
throw new ArgumentNullException("productId");
|
||||
|
||||
if (quantity <= 0)
|
||||
{
|
||||
throw new ArgumentException("The quantity of Product in an Order cannot be equal or less than cero");
|
||||
}
|
||||
|
||||
//check discount values
|
||||
if (discount < 0)
|
||||
discount = 0;
|
||||
|
||||
if (discount > 100)
|
||||
discount = 100;
|
||||
|
||||
//create new order line
|
||||
var newOrderItem = new OrderItem()
|
||||
{
|
||||
OrderId = this.Id,
|
||||
ProductId = productId,
|
||||
Quantity = quantity,
|
||||
FulfillmentRemaining = quantity,
|
||||
Discount = discount,
|
||||
UnitPrice = unitPrice
|
||||
};
|
||||
|
||||
//set identity
|
||||
newOrderItem.GenerateNewIdentity();
|
||||
|
||||
//add order item
|
||||
this.OrderItems.Add(newOrderItem);
|
||||
|
||||
//return added orderline
|
||||
return newOrderItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,29 +7,25 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel
|
||||
{
|
||||
public class OrderItem : Entity
|
||||
{
|
||||
//(CDLTLL) Might remove this constructor so
|
||||
// just with a method in the Order-AggregateRoot you can add an OrderItem..
|
||||
//public OrderItem(Guid itemId, decimal itemPrice, int quantity)
|
||||
//{
|
||||
// this.Id = itemId;
|
||||
// this.ItemPrice = itemPrice;
|
||||
// this.Quantity = quantity;
|
||||
// this.FulfillmentRemaining = quantity; <---- Put this logic into the AggregateRoot method AddOrderItem()
|
||||
//}
|
||||
public OrderItem() { } // Infrastructure. EF might need a plain constructor. Do not use.
|
||||
|
||||
protected OrderItem() { } // Infrastructure. EF might need a plain constructor. Do not use.
|
||||
//NOTE: The OrderItem Id (Id) comes from the Entity base class
|
||||
|
||||
public Guid ItemId { get; set; }
|
||||
public Guid ProductId { get; set; }
|
||||
|
||||
public decimal ItemPrice { get; set; }
|
||||
public Guid OrderId { get; set; }
|
||||
|
||||
public decimal UnitPrice { get; set; }
|
||||
|
||||
public int Quantity { get; set; }
|
||||
|
||||
public decimal Discount { get; set; }
|
||||
|
||||
public int FulfillmentRemaining { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("ID: {0}, Quantity: {1}, Fulfillment Remaing: {2}", this.ItemId, this.Quantity, this.FulfillmentRemaining);
|
||||
return String.Format("Product Id: {0}, Quantity: {1}, Fulfillment Remaing: {2}", this.Id, this.Quantity, this.FulfillmentRemaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.SqlData.Queries
|
||||
var orders = await _dbContext.Orders
|
||||
.Include(o => o.ShippingAddress)
|
||||
.Include(o => o.BillingAddress)
|
||||
//.Include(o => o.Items)
|
||||
.Include(o => o.OrderItems)
|
||||
.ToListAsync<Order>();
|
||||
|
||||
// Dynamically generated a Response-Model that includes only the fields you need in the response.
|
||||
@ -33,13 +33,59 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.SqlData.Queries
|
||||
dynamic response = orders.Select(o => new
|
||||
{
|
||||
id = o.Id,
|
||||
orderNumber = o.OrderNumber,
|
||||
buyerId = o.BuyerId,
|
||||
orderDate = o.OrderDate,
|
||||
status = o.Status,
|
||||
shippingAddress = o.ShippingAddress,
|
||||
billingAddress = o.BillingAddress,
|
||||
//items = o.Items.Select(i => i.Content)
|
||||
orderItems = o.OrderItems.Select(i => new
|
||||
{
|
||||
id = i.Id,
|
||||
productId = i.ProductId,
|
||||
unitPrice = i.UnitPrice,
|
||||
quantity = i.Quantity,
|
||||
discount = i.Discount
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public async Task<dynamic> GetOrderById(Guid orderId)
|
||||
{
|
||||
var order = await _dbContext.Orders
|
||||
.Include(o => o.ShippingAddress)
|
||||
.Include(o => o.BillingAddress)
|
||||
.Include(o => o.OrderItems)
|
||||
.Where(o => o.Id == orderId)
|
||||
.SingleOrDefaultAsync<Order>();
|
||||
|
||||
// Dynamically generated a Response-Model that includes only the fields you need in the response.
|
||||
// This keeps the JSON response minimal.
|
||||
// Could also use var
|
||||
dynamic response = new
|
||||
{
|
||||
id = order.Id,
|
||||
orderNumber = order.OrderNumber,
|
||||
buyerId = order.BuyerId,
|
||||
orderDate = order.OrderDate,
|
||||
status = order.Status,
|
||||
shippingAddress = order.ShippingAddress,
|
||||
billingAddress = order.BillingAddress,
|
||||
orderItems = order.OrderItems.Select(i => new
|
||||
{
|
||||
id = i.Id,
|
||||
productId = i.ProductId,
|
||||
unitPrice = i.UnitPrice,
|
||||
quantity = i.Quantity,
|
||||
discount = i.Discount
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Services.Ordering.SqlData.UnitOfWork
|
||||
{
|
||||
public class DbContextUtil
|
||||
{
|
||||
public static DbContextOptions<OrderingDbContext> CreateNewContextOptionsForInMemoryDB()
|
||||
{
|
||||
// Create a fresh service provider, and therefore a fresh
|
||||
// InMemory database instance.
|
||||
var serviceProvider = new ServiceCollection()
|
||||
.AddEntityFrameworkInMemoryDatabase()
|
||||
.BuildServiceProvider();
|
||||
|
||||
// Create a new options instance telling the context to use an
|
||||
// InMemory database and the new service provider.
|
||||
var builder = new DbContextOptionsBuilder<OrderingDbContext>();
|
||||
builder.UseInMemoryDatabase()
|
||||
.UseInternalServiceProvider(serviceProvider);
|
||||
|
||||
return builder.Options;
|
||||
}
|
||||
|
||||
public static DbContextOptions<OrderingDbContext> CreateNewContextOptionsForSqlDB()
|
||||
{
|
||||
// Create a new options instance telling the context to use a Sql database
|
||||
var builder = new DbContextOptionsBuilder<OrderingDbContext>();
|
||||
|
||||
//SQL LOCALDB
|
||||
builder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Microsoft.eShopOnContainers.Services.OrderingDb;Trusted_Connection=True;");
|
||||
|
||||
return builder.Options;
|
||||
}
|
||||
}
|
||||
}
|
@ -27,5 +27,21 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.SqlData.UnitOfWork
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
// Add your customizations after calling base.OnModelCreating(builder);
|
||||
|
||||
//Sequence to be used as part of the OrderNumber
|
||||
modelBuilder.HasSequence<int>("OrderSequences", schema: "shared")
|
||||
.StartsAt(1001)
|
||||
.IncrementsBy(1);
|
||||
|
||||
modelBuilder.Entity<Order>()
|
||||
.Property(o => o.SequenceNumber)
|
||||
.HasDefaultValueSql("NEXT VALUE FOR shared.OrderSequences");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,15 @@
|
||||
"Microsoft.EntityFrameworkCore": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
|
||||
"NETStandard.Library": "1.6.0",
|
||||
"Ordering.Domain": "1.0.0-*"
|
||||
"Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.0",
|
||||
"Ordering.Domain": "1.0.0-*",
|
||||
"Microsoft.EntityFrameworkCore.InMemory": "1.0.0"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netstandard1.6": {
|
||||
"imports": "dnxcore50"
|
||||
"imports": [ "dnxcore50", "portable-net451+win8" ]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.SqlData.UnitOfWork;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.RepositoryContracts;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.SqlData.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@ -15,49 +17,21 @@ namespace DataIntegrationTests
|
||||
// http://ef.readthedocs.io/en/latest/miscellaneous/testing.html
|
||||
public class Tests
|
||||
{
|
||||
private static DbContextOptions<OrderingDbContext> CreateNewContextOptionsForInMemoryDB()
|
||||
{
|
||||
// Create a fresh service provider, and therefore a fresh
|
||||
// InMemory database instance.
|
||||
var serviceProvider = new ServiceCollection()
|
||||
.AddEntityFrameworkInMemoryDatabase()
|
||||
.BuildServiceProvider();
|
||||
|
||||
// Create a new options instance telling the context to use an
|
||||
// InMemory database and the new service provider.
|
||||
var builder = new DbContextOptionsBuilder<OrderingDbContext>();
|
||||
builder.UseInMemoryDatabase()
|
||||
.UseInternalServiceProvider(serviceProvider);
|
||||
|
||||
return builder.Options;
|
||||
}
|
||||
|
||||
private static DbContextOptions<OrderingDbContext> CreateNewContextOptionsForSqlDB()
|
||||
{
|
||||
// Create a new options instance telling the context to use a Sql database
|
||||
var builder = new DbContextOptionsBuilder<OrderingDbContext>();
|
||||
|
||||
//SQL LOCALDB
|
||||
builder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Microsoft.eShopOnContainers.Services.OrderingDb;Trusted_Connection=True;");
|
||||
|
||||
return builder.Options;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Add_orders_to_database()
|
||||
public void Add_order_to_data_model()
|
||||
{
|
||||
// All contexts that share the same service provider will share the same database
|
||||
|
||||
//Using InMemory DB
|
||||
var options = CreateNewContextOptionsForInMemoryDB();
|
||||
//var options = DbContextUtil.CreateNewContextOptionsForInMemoryDB();
|
||||
|
||||
//Using Sql LocalDB
|
||||
//var options = CreateNewContextOptionsForSqlDB();
|
||||
|
||||
var options = DbContextUtil.CreateNewContextOptionsForSqlDB();
|
||||
|
||||
// Run the test against one instance of the context
|
||||
using (var context = new OrderingDbContext(options))
|
||||
{
|
||||
IOrderRepository orderRepository = new OrderRepository(context);
|
||||
|
||||
//Create generic Address ValueObject
|
||||
Address sampleAddress = new Address("15703 NE 61st Ct.",
|
||||
@ -72,10 +46,20 @@ namespace DataIntegrationTests
|
||||
);
|
||||
//Create sample Orders
|
||||
Order order1 = new Order(Guid.NewGuid(), sampleAddress, sampleAddress);
|
||||
context.Orders.Add(order1);
|
||||
context.SaveChanges();
|
||||
|
||||
Assert.True(true);
|
||||
//Add a few OrderItems
|
||||
order1.AddNewOrderItem(Guid.NewGuid(), 2, 25, 30);
|
||||
order1.AddNewOrderItem(Guid.NewGuid(), 1, 58, 0);
|
||||
order1.AddNewOrderItem(Guid.NewGuid(), 1, 60, 0);
|
||||
order1.AddNewOrderItem(Guid.NewGuid(), 3, 12, 0);
|
||||
order1.AddNewOrderItem(Guid.NewGuid(), 5, 3, 0);
|
||||
|
||||
orderRepository.Add(order1);
|
||||
|
||||
//With no Async Repository
|
||||
//context.Orders.Add(order1);
|
||||
//context.SaveChanges();
|
||||
|
||||
}
|
||||
|
||||
//// Use a separate instance of the context to verify correct data was saved to database
|
||||
@ -87,7 +71,7 @@ namespace DataIntegrationTests
|
||||
.ToList();
|
||||
//Could be using .Load() if you don't want to create a List
|
||||
|
||||
//SAMPLE
|
||||
//OTHER SAMPLE
|
||||
//var company = context.Companies
|
||||
// .Include(co => co.Employees).ThenInclude(emp => emp.Employee_Car)
|
||||
// .Include(co => co.Employees).ThenInclude(emp => emp.Employee_Country)
|
||||
|
Loading…
x
Reference in New Issue
Block a user