@ -1,41 +1,35 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; | |||
namespace Ordering.Infrastructure.EntityConfigurations | |||
class BuyerEntityTypeConfiguration | |||
: IEntityTypeConfiguration<Buyer> | |||
{ | |||
class BuyerEntityTypeConfiguration | |||
: IEntityTypeConfiguration<Buyer> | |||
public void Configure(EntityTypeBuilder<Buyer> buyerConfiguration) | |||
{ | |||
public void Configure(EntityTypeBuilder<Buyer> buyerConfiguration) | |||
{ | |||
buyerConfiguration.ToTable("buyers", OrderingContext.DEFAULT_SCHEMA); | |||
buyerConfiguration.ToTable("buyers", OrderingContext.DEFAULT_SCHEMA); | |||
buyerConfiguration.HasKey(b => b.Id); | |||
buyerConfiguration.HasKey(b => b.Id); | |||
buyerConfiguration.Ignore(b => b.DomainEvents); | |||
buyerConfiguration.Ignore(b => b.DomainEvents); | |||
buyerConfiguration.Property(b => b.Id) | |||
.UseHiLo("buyerseq", OrderingContext.DEFAULT_SCHEMA); | |||
buyerConfiguration.Property(b => b.Id) | |||
.UseHiLo("buyerseq", OrderingContext.DEFAULT_SCHEMA); | |||
buyerConfiguration.Property(b => b.IdentityGuid) | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
buyerConfiguration.Property(b => b.IdentityGuid) | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
buyerConfiguration.HasIndex("IdentityGuid") | |||
.IsUnique(true); | |||
buyerConfiguration.HasIndex("IdentityGuid") | |||
.IsUnique(true); | |||
buyerConfiguration.Property(b => b.Name); | |||
buyerConfiguration.Property(b => b.Name); | |||
buyerConfiguration.HasMany(b => b.PaymentMethods) | |||
.WithOne() | |||
.HasForeignKey("BuyerId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
buyerConfiguration.HasMany(b => b.PaymentMethods) | |||
.WithOne() | |||
.HasForeignKey("BuyerId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
var navigation = buyerConfiguration.Metadata.FindNavigation(nameof(Buyer.PaymentMethods)); | |||
var navigation = buyerConfiguration.Metadata.FindNavigation(nameof(Buyer.PaymentMethods)); | |||
navigation.SetPropertyAccessMode(PropertyAccessMode.Field); | |||
} | |||
navigation.SetPropertyAccessMode(PropertyAccessMode.Field); | |||
} | |||
} |
@ -1,27 +1,21 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; | |||
namespace Ordering.Infrastructure.EntityConfigurations | |||
class CardTypeEntityTypeConfiguration | |||
: IEntityTypeConfiguration<CardType> | |||
{ | |||
class CardTypeEntityTypeConfiguration | |||
: IEntityTypeConfiguration<CardType> | |||
public void Configure(EntityTypeBuilder<CardType> cardTypesConfiguration) | |||
{ | |||
public void Configure(EntityTypeBuilder<CardType> cardTypesConfiguration) | |||
{ | |||
cardTypesConfiguration.ToTable("cardtypes", OrderingContext.DEFAULT_SCHEMA); | |||
cardTypesConfiguration.ToTable("cardtypes", OrderingContext.DEFAULT_SCHEMA); | |||
cardTypesConfiguration.HasKey(ct => ct.Id); | |||
cardTypesConfiguration.HasKey(ct => ct.Id); | |||
cardTypesConfiguration.Property(ct => ct.Id) | |||
.HasDefaultValue(1) | |||
.ValueGeneratedNever() | |||
.IsRequired(); | |||
cardTypesConfiguration.Property(ct => ct.Id) | |||
.HasDefaultValue(1) | |||
.ValueGeneratedNever() | |||
.IsRequired(); | |||
cardTypesConfiguration.Property(ct => ct.Name) | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
} | |||
cardTypesConfiguration.Property(ct => ct.Name) | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
} | |||
} |
@ -1,19 +1,13 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; | |||
namespace Ordering.Infrastructure.EntityConfigurations | |||
class ClientRequestEntityTypeConfiguration | |||
: IEntityTypeConfiguration<ClientRequest> | |||
{ | |||
class ClientRequestEntityTypeConfiguration | |||
: IEntityTypeConfiguration<ClientRequest> | |||
public void Configure(EntityTypeBuilder<ClientRequest> requestConfiguration) | |||
{ | |||
public void Configure(EntityTypeBuilder<ClientRequest> requestConfiguration) | |||
{ | |||
requestConfiguration.ToTable("requests", OrderingContext.DEFAULT_SCHEMA); | |||
requestConfiguration.HasKey(cr => cr.Id); | |||
requestConfiguration.Property(cr => cr.Name).IsRequired(); | |||
requestConfiguration.Property(cr => cr.Time).IsRequired(); | |||
} | |||
requestConfiguration.ToTable("requests", OrderingContext.DEFAULT_SCHEMA); | |||
requestConfiguration.HasKey(cr => cr.Id); | |||
requestConfiguration.Property(cr => cr.Name).IsRequired(); | |||
requestConfiguration.Property(cr => cr.Time).IsRequired(); | |||
} | |||
} |
@ -1,86 +1,78 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
using System; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; | |||
namespace Ordering.Infrastructure.EntityConfigurations | |||
class OrderEntityTypeConfiguration : IEntityTypeConfiguration<Order> | |||
{ | |||
class OrderEntityTypeConfiguration : IEntityTypeConfiguration<Order> | |||
public void Configure(EntityTypeBuilder<Order> orderConfiguration) | |||
{ | |||
public void Configure(EntityTypeBuilder<Order> orderConfiguration) | |||
{ | |||
orderConfiguration.ToTable("orders", OrderingContext.DEFAULT_SCHEMA); | |||
orderConfiguration.ToTable("orders", OrderingContext.DEFAULT_SCHEMA); | |||
orderConfiguration.HasKey(o => o.Id); | |||
orderConfiguration.HasKey(o => o.Id); | |||
orderConfiguration.Ignore(b => b.DomainEvents); | |||
orderConfiguration.Ignore(b => b.DomainEvents); | |||
orderConfiguration.Property(o => o.Id) | |||
.UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); | |||
orderConfiguration.Property(o => o.Id) | |||
.UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); | |||
//Address value object persisted as owned entity type supported since EF Core 2.0 | |||
orderConfiguration | |||
.OwnsOne(o => o.Address, a => | |||
{ | |||
// Explicit configuration of the shadow key property in the owned type | |||
// as a workaround for a documented issue in EF Core 5: https://github.com/dotnet/efcore/issues/20740 | |||
a.Property<int>("OrderId") | |||
.UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); | |||
a.WithOwner(); | |||
}); | |||
//Address value object persisted as owned entity type supported since EF Core 2.0 | |||
orderConfiguration | |||
.OwnsOne(o => o.Address, a => | |||
{ | |||
// Explicit configuration of the shadow key property in the owned type | |||
// as a workaround for a documented issue in EF Core 5: https://github.com/dotnet/efcore/issues/20740 | |||
a.Property<int>("OrderId") | |||
.UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); | |||
a.WithOwner(); | |||
}); | |||
orderConfiguration | |||
.Property<int?>("_buyerId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("BuyerId") | |||
.IsRequired(false); | |||
orderConfiguration | |||
.Property<int?>("_buyerId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("BuyerId") | |||
.IsRequired(false); | |||
orderConfiguration | |||
.Property<DateTime>("_orderDate") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("OrderDate") | |||
.IsRequired(); | |||
orderConfiguration | |||
.Property<DateTime>("_orderDate") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("OrderDate") | |||
.IsRequired(); | |||
orderConfiguration | |||
.Property<int>("_orderStatusId") | |||
// .HasField("_orderStatusId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("OrderStatusId") | |||
.IsRequired(); | |||
orderConfiguration | |||
.Property<int>("_orderStatusId") | |||
// .HasField("_orderStatusId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("OrderStatusId") | |||
.IsRequired(); | |||
orderConfiguration | |||
.Property<int?>("_paymentMethodId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("PaymentMethodId") | |||
.IsRequired(false); | |||
orderConfiguration | |||
.Property<int?>("_paymentMethodId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("PaymentMethodId") | |||
.IsRequired(false); | |||
orderConfiguration.Property<string>("Description").IsRequired(false); | |||
orderConfiguration.Property<string>("Description").IsRequired(false); | |||
var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems)); | |||
var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems)); | |||
// DDD Patterns comment: | |||
//Set as field (New since EF 1.1) to access the OrderItem collection property through its field | |||
navigation.SetPropertyAccessMode(PropertyAccessMode.Field); | |||
// DDD Patterns comment: | |||
//Set as field (New since EF 1.1) to access the OrderItem collection property through its field | |||
navigation.SetPropertyAccessMode(PropertyAccessMode.Field); | |||
orderConfiguration.HasOne<PaymentMethod>() | |||
.WithMany() | |||
// .HasForeignKey("PaymentMethodId") | |||
.HasForeignKey("_paymentMethodId") | |||
.IsRequired(false) | |||
.OnDelete(DeleteBehavior.Restrict); | |||
orderConfiguration.HasOne<PaymentMethod>() | |||
.WithMany() | |||
// .HasForeignKey("PaymentMethodId") | |||
.HasForeignKey("_paymentMethodId") | |||
.IsRequired(false) | |||
.OnDelete(DeleteBehavior.Restrict); | |||
orderConfiguration.HasOne<Buyer>() | |||
.WithMany() | |||
.IsRequired(false) | |||
// .HasForeignKey("BuyerId"); | |||
.HasForeignKey("_buyerId"); | |||
orderConfiguration.HasOne<Buyer>() | |||
.WithMany() | |||
.IsRequired(false) | |||
// .HasForeignKey("BuyerId"); | |||
.HasForeignKey("_buyerId"); | |||
orderConfiguration.HasOne(o => o.OrderStatus) | |||
.WithMany() | |||
// .HasForeignKey("OrderStatusId"); | |||
.HasForeignKey("_orderStatusId"); | |||
} | |||
orderConfiguration.HasOne(o => o.OrderStatus) | |||
.WithMany() | |||
// .HasForeignKey("OrderStatusId"); | |||
.HasForeignKey("_orderStatusId"); | |||
} | |||
} |
@ -1,59 +1,53 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; | |||
namespace Ordering.Infrastructure.EntityConfigurations | |||
class OrderItemEntityTypeConfiguration | |||
: IEntityTypeConfiguration<OrderItem> | |||
{ | |||
class OrderItemEntityTypeConfiguration | |||
: IEntityTypeConfiguration<OrderItem> | |||
public void Configure(EntityTypeBuilder<OrderItem> orderItemConfiguration) | |||
{ | |||
public void Configure(EntityTypeBuilder<OrderItem> orderItemConfiguration) | |||
{ | |||
orderItemConfiguration.ToTable("orderItems", OrderingContext.DEFAULT_SCHEMA); | |||
orderItemConfiguration.HasKey(o => o.Id); | |||
orderItemConfiguration.Ignore(b => b.DomainEvents); | |||
orderItemConfiguration.Property(o => o.Id) | |||
.UseHiLo("orderitemseq"); | |||
orderItemConfiguration.Property<int>("OrderId") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<decimal>("_discount") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Discount") | |||
.IsRequired(); | |||
orderItemConfiguration.Property<int>("ProductId") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<string>("_productName") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("ProductName") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<decimal>("_unitPrice") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("UnitPrice") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<int>("_units") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Units") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<string>("_pictureUrl") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("PictureUrl") | |||
.IsRequired(false); | |||
} | |||
orderItemConfiguration.ToTable("orderItems", OrderingContext.DEFAULT_SCHEMA); | |||
orderItemConfiguration.HasKey(o => o.Id); | |||
orderItemConfiguration.Ignore(b => b.DomainEvents); | |||
orderItemConfiguration.Property(o => o.Id) | |||
.UseHiLo("orderitemseq"); | |||
orderItemConfiguration.Property<int>("OrderId") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<decimal>("_discount") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Discount") | |||
.IsRequired(); | |||
orderItemConfiguration.Property<int>("ProductId") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<string>("_productName") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("ProductName") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<decimal>("_unitPrice") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("UnitPrice") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<int>("_units") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Units") | |||
.IsRequired(); | |||
orderItemConfiguration | |||
.Property<string>("_pictureUrl") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("PictureUrl") | |||
.IsRequired(false); | |||
} | |||
} |
@ -1,27 +1,21 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; | |||
namespace Ordering.Infrastructure.EntityConfigurations | |||
class OrderStatusEntityTypeConfiguration | |||
: IEntityTypeConfiguration<OrderStatus> | |||
{ | |||
class OrderStatusEntityTypeConfiguration | |||
: IEntityTypeConfiguration<OrderStatus> | |||
public void Configure(EntityTypeBuilder<OrderStatus> orderStatusConfiguration) | |||
{ | |||
public void Configure(EntityTypeBuilder<OrderStatus> orderStatusConfiguration) | |||
{ | |||
orderStatusConfiguration.ToTable("orderstatus", OrderingContext.DEFAULT_SCHEMA); | |||
orderStatusConfiguration.ToTable("orderstatus", OrderingContext.DEFAULT_SCHEMA); | |||
orderStatusConfiguration.HasKey(o => o.Id); | |||
orderStatusConfiguration.HasKey(o => o.Id); | |||
orderStatusConfiguration.Property(o => o.Id) | |||
.HasDefaultValue(1) | |||
.ValueGeneratedNever() | |||
.IsRequired(); | |||
orderStatusConfiguration.Property(o => o.Id) | |||
.HasDefaultValue(1) | |||
.ValueGeneratedNever() | |||
.IsRequired(); | |||
orderStatusConfiguration.Property(o => o.Name) | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
} | |||
orderStatusConfiguration.Property(o => o.Name) | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
} | |||
} |
@ -1,65 +1,58 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
using System; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; | |||
namespace Ordering.Infrastructure.EntityConfigurations | |||
class PaymentMethodEntityTypeConfiguration | |||
: IEntityTypeConfiguration<PaymentMethod> | |||
{ | |||
class PaymentMethodEntityTypeConfiguration | |||
: IEntityTypeConfiguration<PaymentMethod> | |||
public void Configure(EntityTypeBuilder<PaymentMethod> paymentConfiguration) | |||
{ | |||
public void Configure(EntityTypeBuilder<PaymentMethod> paymentConfiguration) | |||
{ | |||
paymentConfiguration.ToTable("paymentmethods", OrderingContext.DEFAULT_SCHEMA); | |||
paymentConfiguration.HasKey(b => b.Id); | |||
paymentConfiguration.Ignore(b => b.DomainEvents); | |||
paymentConfiguration.Property(b => b.Id) | |||
.UseHiLo("paymentseq", OrderingContext.DEFAULT_SCHEMA); | |||
paymentConfiguration.Property<int>("BuyerId") | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<string>("_cardHolderName") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("CardHolderName") | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<string>("_alias") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Alias") | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<string>("_cardNumber") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("CardNumber") | |||
.HasMaxLength(25) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<DateTime>("_expiration") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Expiration") | |||
.HasMaxLength(25) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<int>("_cardTypeId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("CardTypeId") | |||
.IsRequired(); | |||
paymentConfiguration.HasOne(p => p.CardType) | |||
.WithMany() | |||
.HasForeignKey("_cardTypeId"); | |||
} | |||
paymentConfiguration.ToTable("paymentmethods", OrderingContext.DEFAULT_SCHEMA); | |||
paymentConfiguration.HasKey(b => b.Id); | |||
paymentConfiguration.Ignore(b => b.DomainEvents); | |||
paymentConfiguration.Property(b => b.Id) | |||
.UseHiLo("paymentseq", OrderingContext.DEFAULT_SCHEMA); | |||
paymentConfiguration.Property<int>("BuyerId") | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<string>("_cardHolderName") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("CardHolderName") | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<string>("_alias") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Alias") | |||
.HasMaxLength(200) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<string>("_cardNumber") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("CardNumber") | |||
.HasMaxLength(25) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<DateTime>("_expiration") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("Expiration") | |||
.HasMaxLength(25) | |||
.IsRequired(); | |||
paymentConfiguration | |||
.Property<int>("_cardTypeId") | |||
.UsePropertyAccessMode(PropertyAccessMode.Field) | |||
.HasColumnName("CardTypeId") | |||
.IsRequired(); | |||
paymentConfiguration.HasOne(p => p.CardType) | |||
.WithMany() | |||
.HasForeignKey("_cardTypeId"); | |||
} | |||
} |
@ -1,11 +1,8 @@ | |||
using System; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency | |||
public class ClientRequest | |||
{ | |||
public class ClientRequest | |||
{ | |||
public Guid Id { get; set; } | |||
public string Name { get; set; } | |||
public DateTime Time { get; set; } | |||
} | |||
public Guid Id { get; set; } | |||
public string Name { get; set; } | |||
public DateTime Time { get; set; } | |||
} |
@ -1,12 +1,8 @@ | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency | |||
public interface IRequestManager | |||
{ | |||
public interface IRequestManager | |||
{ | |||
Task<bool> ExistAsync(Guid id); | |||
Task<bool> ExistAsync(Guid id); | |||
Task CreateRequestForCommandAsync<T>(Guid id); | |||
} | |||
Task CreateRequestForCommandAsync<T>(Guid id); | |||
} |
@ -1,43 +1,38 @@ | |||
using Ordering.Domain.Exceptions; | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency | |||
public class RequestManager : IRequestManager | |||
{ | |||
public class RequestManager : IRequestManager | |||
{ | |||
private readonly OrderingContext _context; | |||
private readonly OrderingContext _context; | |||
public RequestManager(OrderingContext context) | |||
{ | |||
_context = context ?? throw new ArgumentNullException(nameof(context)); | |||
} | |||
public RequestManager(OrderingContext context) | |||
{ | |||
_context = context ?? throw new ArgumentNullException(nameof(context)); | |||
} | |||
public async Task<bool> ExistAsync(Guid id) | |||
{ | |||
var request = await _context. | |||
FindAsync<ClientRequest>(id); | |||
public async Task<bool> ExistAsync(Guid id) | |||
{ | |||
var request = await _context. | |||
FindAsync<ClientRequest>(id); | |||
return request != null; | |||
} | |||
return request != null; | |||
} | |||
public async Task CreateRequestForCommandAsync<T>(Guid id) | |||
{ | |||
var exists = await ExistAsync(id); | |||
public async Task CreateRequestForCommandAsync<T>(Guid id) | |||
{ | |||
var exists = await ExistAsync(id); | |||
var request = exists ? | |||
throw new OrderingDomainException($"Request with {id} already exists") : | |||
new ClientRequest() | |||
{ | |||
Id = id, | |||
Name = typeof(T).Name, | |||
Time = DateTime.UtcNow | |||
}; | |||
var request = exists ? | |||
throw new OrderingDomainException($"Request with {id} already exists") : | |||
new ClientRequest() | |||
{ | |||
Id = id, | |||
Name = typeof(T).Name, | |||
Time = DateTime.UtcNow | |||
}; | |||
_context.Add(request); | |||
_context.Add(request); | |||
await _context.SaveChangesAsync(); | |||
} | |||
await _context.SaveChangesAsync(); | |||
} | |||
} |
@ -1,156 +1,141 @@ | |||
using MediatR; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Design; | |||
using Microsoft.EntityFrameworkCore.Storage; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; | |||
using Ordering.Infrastructure; | |||
using Ordering.Infrastructure.EntityConfigurations; | |||
using System; | |||
using System.Data; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; | |||
public class OrderingContext : DbContext, IUnitOfWork | |||
{ | |||
public class OrderingContext : DbContext, IUnitOfWork | |||
public const string DEFAULT_SCHEMA = "ordering"; | |||
public DbSet<Order> Orders { get; set; } | |||
public DbSet<OrderItem> OrderItems { get; set; } | |||
public DbSet<PaymentMethod> Payments { get; set; } | |||
public DbSet<Buyer> Buyers { get; set; } | |||
public DbSet<CardType> CardTypes { get; set; } | |||
public DbSet<OrderStatus> OrderStatus { get; set; } | |||
private readonly IMediator _mediator; | |||
private IDbContextTransaction _currentTransaction; | |||
public OrderingContext(DbContextOptions<OrderingContext> options) : base(options) { } | |||
public IDbContextTransaction GetCurrentTransaction() => _currentTransaction; | |||
public bool HasActiveTransaction => _currentTransaction != null; | |||
public OrderingContext(DbContextOptions<OrderingContext> options, IMediator mediator) : base(options) | |||
{ | |||
public const string DEFAULT_SCHEMA = "ordering"; | |||
public DbSet<Order> Orders { get; set; } | |||
public DbSet<OrderItem> OrderItems { get; set; } | |||
public DbSet<PaymentMethod> Payments { get; set; } | |||
public DbSet<Buyer> Buyers { get; set; } | |||
public DbSet<CardType> CardTypes { get; set; } | |||
public DbSet<OrderStatus> OrderStatus { get; set; } | |||
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); | |||
private readonly IMediator _mediator; | |||
private IDbContextTransaction _currentTransaction; | |||
public OrderingContext(DbContextOptions<OrderingContext> options) : base(options) { } | |||
System.Diagnostics.Debug.WriteLine("OrderingContext::ctor ->" + this.GetHashCode()); | |||
} | |||
public IDbContextTransaction GetCurrentTransaction() => _currentTransaction; | |||
protected override void OnModelCreating(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder.ApplyConfiguration(new ClientRequestEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new PaymentMethodEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new OrderEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new OrderItemEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new CardTypeEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new OrderStatusEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new BuyerEntityTypeConfiguration()); | |||
} | |||
public bool HasActiveTransaction => _currentTransaction != null; | |||
public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)) | |||
{ | |||
// Dispatch Domain Events collection. | |||
// Choices: | |||
// A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including | |||
// side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime | |||
// B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions. | |||
// You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers. | |||
await _mediator.DispatchDomainEventsAsync(this); | |||
// After executing this line all the changes (from the Command Handler and Domain Event Handlers) | |||
// performed through the DbContext will be committed | |||
var result = await base.SaveChangesAsync(cancellationToken); | |||
return true; | |||
} | |||
public OrderingContext(DbContextOptions<OrderingContext> options, IMediator mediator) : base(options) | |||
{ | |||
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); | |||
public async Task<IDbContextTransaction> BeginTransactionAsync() | |||
{ | |||
if (_currentTransaction != null) return null; | |||
_currentTransaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted); | |||
System.Diagnostics.Debug.WriteLine("OrderingContext::ctor ->" + this.GetHashCode()); | |||
} | |||
return _currentTransaction; | |||
} | |||
protected override void OnModelCreating(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder.ApplyConfiguration(new ClientRequestEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new PaymentMethodEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new OrderEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new OrderItemEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new CardTypeEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new OrderStatusEntityTypeConfiguration()); | |||
modelBuilder.ApplyConfiguration(new BuyerEntityTypeConfiguration()); | |||
} | |||
public async Task CommitTransactionAsync(IDbContextTransaction transaction) | |||
{ | |||
if (transaction == null) throw new ArgumentNullException(nameof(transaction)); | |||
if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current"); | |||
public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)) | |||
try | |||
{ | |||
// Dispatch Domain Events collection. | |||
// Choices: | |||
// A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including | |||
// side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime | |||
// B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions. | |||
// You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers. | |||
await _mediator.DispatchDomainEventsAsync(this); | |||
// After executing this line all the changes (from the Command Handler and Domain Event Handlers) | |||
// performed through the DbContext will be committed | |||
var result = await base.SaveChangesAsync(cancellationToken); | |||
return true; | |||
await SaveChangesAsync(); | |||
transaction.Commit(); | |||
} | |||
public async Task<IDbContextTransaction> BeginTransactionAsync() | |||
catch | |||
{ | |||
if (_currentTransaction != null) return null; | |||
_currentTransaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted); | |||
return _currentTransaction; | |||
RollbackTransaction(); | |||
throw; | |||
} | |||
public async Task CommitTransactionAsync(IDbContextTransaction transaction) | |||
finally | |||
{ | |||
if (transaction == null) throw new ArgumentNullException(nameof(transaction)); | |||
if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current"); | |||
try | |||
{ | |||
await SaveChangesAsync(); | |||
transaction.Commit(); | |||
} | |||
catch | |||
{ | |||
RollbackTransaction(); | |||
throw; | |||
} | |||
finally | |||
if (_currentTransaction != null) | |||
{ | |||
if (_currentTransaction != null) | |||
{ | |||
_currentTransaction.Dispose(); | |||
_currentTransaction = null; | |||
} | |||
_currentTransaction.Dispose(); | |||
_currentTransaction = null; | |||
} | |||
} | |||
} | |||
public void RollbackTransaction() | |||
public void RollbackTransaction() | |||
{ | |||
try | |||
{ | |||
try | |||
{ | |||
_currentTransaction?.Rollback(); | |||
} | |||
finally | |||
_currentTransaction?.Rollback(); | |||
} | |||
finally | |||
{ | |||
if (_currentTransaction != null) | |||
{ | |||
if (_currentTransaction != null) | |||
{ | |||
_currentTransaction.Dispose(); | |||
_currentTransaction = null; | |||
} | |||
_currentTransaction.Dispose(); | |||
_currentTransaction = null; | |||
} | |||
} | |||
} | |||
} | |||
public class OrderingContextDesignFactory : IDesignTimeDbContextFactory<OrderingContext> | |||
public class OrderingContextDesignFactory : IDesignTimeDbContextFactory<OrderingContext> | |||
{ | |||
public OrderingContext CreateDbContext(string[] args) | |||
{ | |||
public OrderingContext CreateDbContext(string[] args) | |||
{ | |||
var optionsBuilder = new DbContextOptionsBuilder<OrderingContext>() | |||
.UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;Integrated Security=true"); | |||
var optionsBuilder = new DbContextOptionsBuilder<OrderingContext>() | |||
.UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;Integrated Security=true"); | |||
return new OrderingContext(optionsBuilder.Options, new NoMediator()); | |||
} | |||
return new OrderingContext(optionsBuilder.Options, new NoMediator()); | |||
} | |||
class NoMediator : IMediator | |||
class NoMediator : IMediator | |||
{ | |||
public Task Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default(CancellationToken)) where TNotification : INotification | |||
{ | |||
public Task Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default(CancellationToken)) where TNotification : INotification | |||
{ | |||
return Task.CompletedTask; | |||
} | |||
return Task.CompletedTask; | |||
} | |||
public Task Publish(object notification, CancellationToken cancellationToken = default) | |||
{ | |||
return Task.CompletedTask; | |||
} | |||
public Task Publish(object notification, CancellationToken cancellationToken = default) | |||
{ | |||
return Task.CompletedTask; | |||
} | |||
public Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default(CancellationToken)) | |||
{ | |||
return Task.FromResult<TResponse>(default(TResponse)); | |||
} | |||
public Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default(CancellationToken)) | |||
{ | |||
return Task.FromResult<TResponse>(default(TResponse)); | |||
} | |||
public Task<object> Send(object request, CancellationToken cancellationToken = default) | |||
{ | |||
return Task.FromResult(default(object)); | |||
} | |||
public Task<object> Send(object request, CancellationToken cancellationToken = default) | |||
{ | |||
return Task.FromResult(default(object)); | |||
} | |||
} | |||
} |
@ -1,68 +1,60 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; | |||
using System; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories | |||
public class BuyerRepository | |||
: IBuyerRepository | |||
{ | |||
public class BuyerRepository | |||
: IBuyerRepository | |||
private readonly OrderingContext _context; | |||
public IUnitOfWork UnitOfWork | |||
{ | |||
private readonly OrderingContext _context; | |||
public IUnitOfWork UnitOfWork | |||
get | |||
{ | |||
get | |||
{ | |||
return _context; | |||
} | |||
} | |||
public BuyerRepository(OrderingContext context) | |||
{ | |||
_context = context ?? throw new ArgumentNullException(nameof(context)); | |||
return _context; | |||
} | |||
} | |||
public Buyer Add(Buyer buyer) | |||
{ | |||
if (buyer.IsTransient()) | |||
{ | |||
return _context.Buyers | |||
.Add(buyer) | |||
.Entity; | |||
} | |||
else | |||
{ | |||
return buyer; | |||
} | |||
} | |||
public BuyerRepository(OrderingContext context) | |||
{ | |||
_context = context ?? throw new ArgumentNullException(nameof(context)); | |||
} | |||
public Buyer Update(Buyer buyer) | |||
public Buyer Add(Buyer buyer) | |||
{ | |||
if (buyer.IsTransient()) | |||
{ | |||
return _context.Buyers | |||
.Update(buyer) | |||
.Entity; | |||
.Add(buyer) | |||
.Entity; | |||
} | |||
public async Task<Buyer> FindAsync(string identity) | |||
else | |||
{ | |||
var buyer = await _context.Buyers | |||
.Include(b => b.PaymentMethods) | |||
.Where(b => b.IdentityGuid == identity) | |||
.SingleOrDefaultAsync(); | |||
return buyer; | |||
} | |||
} | |||
public async Task<Buyer> FindByIdAsync(string id) | |||
{ | |||
var buyer = await _context.Buyers | |||
.Include(b => b.PaymentMethods) | |||
.Where(b => b.Id == int.Parse(id)) | |||
.SingleOrDefaultAsync(); | |||
public Buyer Update(Buyer buyer) | |||
{ | |||
return _context.Buyers | |||
.Update(buyer) | |||
.Entity; | |||
} | |||
return buyer; | |||
} | |||
public async Task<Buyer> FindAsync(string identity) | |||
{ | |||
var buyer = await _context.Buyers | |||
.Include(b => b.PaymentMethods) | |||
.Where(b => b.IdentityGuid == identity) | |||
.SingleOrDefaultAsync(); | |||
return buyer; | |||
} | |||
public async Task<Buyer> FindByIdAsync(string id) | |||
{ | |||
var buyer = await _context.Buyers | |||
.Include(b => b.PaymentMethods) | |||
.Where(b => b.Id == int.Parse(id)) | |||
.SingleOrDefaultAsync(); | |||
return buyer; | |||
} | |||
} |
@ -1,63 +1,55 @@ | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; | |||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; | |||
using System; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories; | |||
public class OrderRepository | |||
: IOrderRepository | |||
{ | |||
public class OrderRepository | |||
: IOrderRepository | |||
{ | |||
private readonly OrderingContext _context; | |||
private readonly OrderingContext _context; | |||
public IUnitOfWork UnitOfWork | |||
public IUnitOfWork UnitOfWork | |||
{ | |||
get | |||
{ | |||
get | |||
{ | |||
return _context; | |||
} | |||
return _context; | |||
} | |||
} | |||
public OrderRepository(OrderingContext context) | |||
{ | |||
_context = context ?? throw new ArgumentNullException(nameof(context)); | |||
} | |||
public OrderRepository(OrderingContext context) | |||
{ | |||
_context = context ?? throw new ArgumentNullException(nameof(context)); | |||
} | |||
public Order Add(Order order) | |||
{ | |||
return _context.Orders.Add(order).Entity; | |||
public Order Add(Order order) | |||
{ | |||
return _context.Orders.Add(order).Entity; | |||
} | |||
} | |||
public async Task<Order> GetAsync(int orderId) | |||
{ | |||
var order = await _context | |||
.Orders | |||
.Include(x => x.Address) | |||
.FirstOrDefaultAsync(o => o.Id == orderId); | |||
if (order == null) | |||
{ | |||
order = _context | |||
public async Task<Order> GetAsync(int orderId) | |||
{ | |||
var order = await _context | |||
.Orders | |||
.Local | |||
.FirstOrDefault(o => o.Id == orderId); | |||
} | |||
if (order != null) | |||
{ | |||
await _context.Entry(order) | |||
.Collection(i => i.OrderItems).LoadAsync(); | |||
await _context.Entry(order) | |||
.Reference(i => i.OrderStatus).LoadAsync(); | |||
} | |||
return order; | |||
.Include(x => x.Address) | |||
.FirstOrDefaultAsync(o => o.Id == orderId); | |||
if (order == null) | |||
{ | |||
order = _context | |||
.Orders | |||
.Local | |||
.FirstOrDefault(o => o.Id == orderId); | |||
} | |||
public void Update(Order order) | |||
if (order != null) | |||
{ | |||
_context.Entry(order).State = EntityState.Modified; | |||
await _context.Entry(order) | |||
.Collection(i => i.OrderItems).LoadAsync(); | |||
await _context.Entry(order) | |||
.Reference(i => i.OrderStatus).LoadAsync(); | |||
} | |||
return order; | |||
} | |||
public void Update(Order order) | |||
{ | |||
_context.Entry(order).State = EntityState.Modified; | |||
} | |||
} |