diff --git a/src/IO.Swagger/Controllers/AuthApi.cs b/src/IO.Swagger/Controllers/AuthApi.cs index 144821d..dee5b2b 100644 --- a/src/IO.Swagger/Controllers/AuthApi.cs +++ b/src/IO.Swagger/Controllers/AuthApi.cs @@ -79,10 +79,7 @@ namespace IO.Swagger.Controllers public virtual async Task LoginUser([FromBody]AuthLoginBody body) { if (!ModelState.IsValid) - { - var errors = ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage)); - return BadRequest(errors); - } + return BadRequest(ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage))); var user = await repository.LoginUser(body); return user == null ? Unauthorized() : Ok(new { token = jwt.GenerateJwt(user.Id) }); } @@ -102,10 +99,7 @@ namespace IO.Swagger.Controllers public async Task RegisterUser([FromBody]AuthRegisterBody body) { if (!ModelState.IsValid) - { - var errors = ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage)); - return BadRequest(errors); - } + return BadRequest(ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage))); var user = await repository.RegisterUser(body); return user == null ? StatusCode(409) : Ok(new { token = jwt.GenerateJwt(user.Id) }); diff --git a/src/IO.Swagger/Controllers/CurrencyApi.cs b/src/IO.Swagger/Controllers/CurrencyApi.cs index e04f389..b0be919 100644 --- a/src/IO.Swagger/Controllers/CurrencyApi.cs +++ b/src/IO.Swagger/Controllers/CurrencyApi.cs @@ -18,6 +18,10 @@ using IO.Swagger.Attributes; using IO.Swagger.Security; using Microsoft.AspNetCore.Authorization; using IO.Swagger.Models.dto; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using IO.Swagger.Repositories; namespace IO.Swagger.Controllers { @@ -26,7 +30,14 @@ namespace IO.Swagger.Controllers /// [ApiController] public class CurrencyApiController : ControllerBase - { + { + private readonly ICurrencyRepository repo; + + public CurrencyApiController(ICurrencyRepository repo) + { + this.repo = repo ?? throw new ArgumentNullException(nameof(repo)); + } + /// /// Add a digital asset to the user's collection /// @@ -86,23 +97,23 @@ namespace IO.Swagger.Controllers /// Currency type created successfully /// Bad Request /// Unauthorized + /// Unprocessable Content [HttpPost] [Route("/v1/api/currency/create")] [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] [ValidateModelState] [SwaggerOperation("CreateCurrency")] - public virtual IActionResult CreateCurrency([FromBody]CurrencyCreateBody body) - { - //TODO: Uncomment the next line to return response 201 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(201); + public virtual async Task CreateCurrency([FromBody]CurrencyCreateBody body) + { + var userIdString = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value; + if (!int.TryParse(userIdString, out int userId)) + return Unauthorized(); - //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(400); + if (!ModelState.IsValid) + return BadRequest(ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage))); - //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(401); - - throw new NotImplementedException(); + var createdCurr = await repo.CreateCurrency(body, userId); + return createdCurr ? StatusCode(201) : StatusCode(422); } /// @@ -112,23 +123,22 @@ namespace IO.Swagger.Controllers /// Successful minting /// Bad Request /// Unauthorized + /// Conflict - User is not owner or currency does not exist [HttpPost] [Route("/v1/api/currency/mint")] [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] [ValidateModelState] [SwaggerOperation("MintCurrency")] - public virtual IActionResult MintCurrency([FromBody]CurrencyMintBody body) - { - //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(200); + public virtual async Task MintCurrency([FromBody]CurrencyMintBody body) + { + var userIdString = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value; + if (!int.TryParse(userIdString, out int userId)) + return Unauthorized(); + if (!ModelState.IsValid) + return BadRequest(ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage))); - //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(400); - - //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(401); - - throw new NotImplementedException(); + var minted = await repo.MintCurrency(body, userId); + return minted ? Ok() : StatusCode(409); } } } diff --git a/src/IO.Swagger/Migrations/20230819185130_Started transactions and currencies.Designer.cs b/src/IO.Swagger/Migrations/20230819185130_Started transactions and currencies.Designer.cs new file mode 100644 index 0000000..29a833f --- /dev/null +++ b/src/IO.Swagger/Migrations/20230819185130_Started transactions and currencies.Designer.cs @@ -0,0 +1,177 @@ +// +using System; +using IO.Swagger.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace IO.Swagger.Migrations +{ + [DbContext(typeof(BankDbContext))] + [Migration("20230819185130_Started transactions and currencies")] + partial class Startedtransactionsandcurrencies + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("IO.Swagger.Models.db.Currency", b => + { + b.Property("CurrencyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("CurrencyId")); + + b.Property("Name") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("Symbol") + .HasMaxLength(4) + .HasColumnType("nvarchar(4)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("CurrencyId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.Transaction", b => + { + b.Property("TransactionId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("TransactionId")); + + b.Property("Amount") + .HasColumnType("real"); + + b.Property("CurrencyId") + .HasColumnType("int"); + + b.Property("FromUserId") + .HasColumnType("int"); + + b.Property("Memo") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("ToUserId") + .HasColumnType("int"); + + b.Property("TransactionTime") + .HasColumnType("datetime2"); + + b.HasKey("TransactionId"); + + b.HasIndex("CurrencyId"); + + b.HasIndex("FromUserId"); + + b.HasIndex("ToUserId"); + + b.ToTable("Transactions"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("LastName") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("Salt") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.Currency", b => + { + b.HasOne("IO.Swagger.Models.db.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.Transaction", b => + { + b.HasOne("IO.Swagger.Models.db.Currency", "Currency") + .WithMany("Transactions") + .HasForeignKey("CurrencyId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("IO.Swagger.Models.db.User", "FromUser") + .WithMany("TransactionsFrom") + .HasForeignKey("FromUserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("IO.Swagger.Models.db.User", "ToUser") + .WithMany("TransactionsTo") + .HasForeignKey("ToUserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Currency"); + + b.Navigation("FromUser"); + + b.Navigation("ToUser"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.Currency", b => + { + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.User", b => + { + b.Navigation("Currencies"); + + b.Navigation("TransactionsFrom"); + + b.Navigation("TransactionsTo"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/IO.Swagger/Migrations/20230819185130_Started transactions and currencies.cs b/src/IO.Swagger/Migrations/20230819185130_Started transactions and currencies.cs new file mode 100644 index 0000000..10656ab --- /dev/null +++ b/src/IO.Swagger/Migrations/20230819185130_Started transactions and currencies.cs @@ -0,0 +1,98 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace IO.Swagger.Migrations +{ + /// + public partial class Startedtransactionsandcurrencies : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Currencies", + columns: table => new + { + CurrencyId = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: true), + Symbol = table.Column(type: "nvarchar(4)", maxLength: 4, nullable: true), + UserId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Currencies", x => x.CurrencyId); + table.ForeignKey( + name: "FK_Currencies_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Transactions", + columns: table => new + { + TransactionId = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + FromUserId = table.Column(type: "int", nullable: false), + ToUserId = table.Column(type: "int", nullable: false), + Amount = table.Column(type: "real", nullable: false), + Memo = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: false), + CurrencyId = table.Column(type: "int", nullable: false), + TransactionTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Transactions", x => x.TransactionId); + table.ForeignKey( + name: "FK_Transactions_Currencies_CurrencyId", + column: x => x.CurrencyId, + principalTable: "Currencies", + principalColumn: "CurrencyId"); + table.ForeignKey( + name: "FK_Transactions_Users_FromUserId", + column: x => x.FromUserId, + principalTable: "Users", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Transactions_Users_ToUserId", + column: x => x.ToUserId, + principalTable: "Users", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_Currencies_UserId", + table: "Currencies", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Transactions_CurrencyId", + table: "Transactions", + column: "CurrencyId"); + + migrationBuilder.CreateIndex( + name: "IX_Transactions_FromUserId", + table: "Transactions", + column: "FromUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Transactions_ToUserId", + table: "Transactions", + column: "ToUserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Transactions"); + + migrationBuilder.DropTable( + name: "Currencies"); + } + } +} diff --git a/src/IO.Swagger/Migrations/BankDbContextModelSnapshot.cs b/src/IO.Swagger/Migrations/BankDbContextModelSnapshot.cs index ca4ee56..917c969 100644 --- a/src/IO.Swagger/Migrations/BankDbContextModelSnapshot.cs +++ b/src/IO.Swagger/Migrations/BankDbContextModelSnapshot.cs @@ -1,4 +1,5 @@ // +using System; using IO.Swagger.Services; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -21,6 +22,71 @@ namespace IO.Swagger.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + modelBuilder.Entity("IO.Swagger.Models.db.Currency", b => + { + b.Property("CurrencyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("CurrencyId")); + + b.Property("Name") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("Symbol") + .HasMaxLength(4) + .HasColumnType("nvarchar(4)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("CurrencyId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.Transaction", b => + { + b.Property("TransactionId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("TransactionId")); + + b.Property("Amount") + .HasColumnType("real"); + + b.Property("CurrencyId") + .HasColumnType("int"); + + b.Property("FromUserId") + .HasColumnType("int"); + + b.Property("Memo") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("ToUserId") + .HasColumnType("int"); + + b.Property("TransactionTime") + .HasColumnType("datetime2"); + + b.HasKey("TransactionId"); + + b.HasIndex("CurrencyId"); + + b.HasIndex("FromUserId"); + + b.HasIndex("ToUserId"); + + b.ToTable("Transactions"); + }); + modelBuilder.Entity("IO.Swagger.Models.db.User", b => { b.Property("Id") @@ -50,6 +116,58 @@ namespace IO.Swagger.Migrations b.ToTable("Users"); }); + + modelBuilder.Entity("IO.Swagger.Models.db.Currency", b => + { + b.HasOne("IO.Swagger.Models.db.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.Transaction", b => + { + b.HasOne("IO.Swagger.Models.db.Currency", "Currency") + .WithMany("Transactions") + .HasForeignKey("CurrencyId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("IO.Swagger.Models.db.User", "FromUser") + .WithMany("TransactionsFrom") + .HasForeignKey("FromUserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("IO.Swagger.Models.db.User", "ToUser") + .WithMany("TransactionsTo") + .HasForeignKey("ToUserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Currency"); + + b.Navigation("FromUser"); + + b.Navigation("ToUser"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.Currency", b => + { + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("IO.Swagger.Models.db.User", b => + { + b.Navigation("Currencies"); + + b.Navigation("TransactionsFrom"); + + b.Navigation("TransactionsTo"); + }); #pragma warning restore 612, 618 } } diff --git a/src/IO.Swagger/Models/db/Currency.cs b/src/IO.Swagger/Models/db/Currency.cs new file mode 100644 index 0000000..d820511 --- /dev/null +++ b/src/IO.Swagger/Models/db/Currency.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; + +namespace IO.Swagger.Models.db +{ + public class Currency + { + public int CurrencyId { get; set; } + [StringLength(32, MinimumLength = 1)] + public string Name { get; set; } + [StringLength(4, MinimumLength = 1)] + public string Symbol { get; set; } + + [ForeignKey("FK_Currency_UserId")] + public int UserId { get; set; } + public User User { get; set; } + + public ICollection Transactions { get; set; } + } +} diff --git a/src/IO.Swagger/Models/db/Transaction.cs b/src/IO.Swagger/Models/db/Transaction.cs new file mode 100644 index 0000000..79e3814 --- /dev/null +++ b/src/IO.Swagger/Models/db/Transaction.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.VisualBasic; +using System; +using System.ComponentModel.DataAnnotations; + +namespace IO.Swagger.Models.db +{ + public class Transaction + { + public int TransactionId { get; set; } + public int FromUserId { get; set; } + public User FromUser { get; set; } + public int ToUserId { get; set; } + public User ToUser { get; set; } + + [Range(0.01, float.MaxValue)] + public float Amount { get; set; } + + [Required] + [StringLength(32, MinimumLength = 2)] + public string Memo { get; set; } + + public Currency Currency { get; set; } + public int CurrencyId { get; set; } + + public DateTime TransactionTime { get; set; } = DateTime.UtcNow; + } +} diff --git a/src/IO.Swagger/Models/db/User.cs b/src/IO.Swagger/Models/db/User.cs index 9a9e29f..acc80c0 100644 --- a/src/IO.Swagger/Models/db/User.cs +++ b/src/IO.Swagger/Models/db/User.cs @@ -1,4 +1,6 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; namespace IO.Swagger.Models.db { @@ -12,6 +14,11 @@ namespace IO.Swagger.Models.db public string LastName { get; set; } public string PasswordHash { get; set; } public string Salt { get; set; } + + public ICollection Currencies { get; set; } + + public ICollection TransactionsFrom { get; set; } + public ICollection TransactionsTo { get; set; } } } diff --git a/src/IO.Swagger/Models/dto/CurrencyMintBody.cs b/src/IO.Swagger/Models/dto/CurrencyMintBody.cs index 704da0d..7f1c62f 100644 --- a/src/IO.Swagger/Models/dto/CurrencyMintBody.cs +++ b/src/IO.Swagger/Models/dto/CurrencyMintBody.cs @@ -31,14 +31,16 @@ namespace IO.Swagger.Models.dto /// [DataMember(Name = "currencyId")] - public int? CurrencyId { get; set; } + [Required] + public int CurrencyId { get; set; } /// /// Gets or Sets Amount /// + [Required] [DataMember(Name = "amount")] - public decimal? Amount { get; set; } + public float Amount { get; set; } /// /// Returns the string presentation of the object diff --git a/src/IO.Swagger/Repositories/CurrencyRepository.cs b/src/IO.Swagger/Repositories/CurrencyRepository.cs new file mode 100644 index 0000000..f921200 --- /dev/null +++ b/src/IO.Swagger/Repositories/CurrencyRepository.cs @@ -0,0 +1,55 @@ +using IO.Swagger.Models.db; +using IO.Swagger.Models.dto; +using IO.Swagger.Services; +using Microsoft.EntityFrameworkCore; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace IO.Swagger.Repositories +{ + public class CurrencyRepository : ICurrencyRepository + { + BankDbContext context; + + public CurrencyRepository(BankDbContext context) + { + this.context = context ?? throw new ArgumentNullException(nameof(context)); + } + + public async Task CreateCurrency(CurrencyCreateBody request, int userId) + { + request.Symbol = request.Symbol.Trim(); + request.Name = request.Name.Trim(); + if (await context.Currencies.AnyAsync(c => c.Symbol == request.Symbol || c.Name.ToLower() == request.Name.ToLower())) + return false; + + await context.Currencies.AddAsync(new Currency + { + Name = request.Name, + Symbol = request.Symbol, + UserId = userId + }); + + return await context.SaveChangesAsync() > 0; + } + + public async Task MintCurrency(CurrencyMintBody request, int userId) + { + var existsAndIsOwner = await context.Currencies.AnyAsync(c => c.CurrencyId == request.CurrencyId && c.UserId == userId); + if (!existsAndIsOwner) + return false; + + await context.Transactions.AddAsync(new Transaction + { + Amount = request.Amount, + CurrencyId = request.CurrencyId, + ToUserId = userId, + FromUserId = userId, + Memo = "Minting" + }); + + return await context.SaveChangesAsync() > 0; + } + } +} diff --git a/src/IO.Swagger/Repositories/ICurrencyRepository.cs b/src/IO.Swagger/Repositories/ICurrencyRepository.cs new file mode 100644 index 0000000..069fbb1 --- /dev/null +++ b/src/IO.Swagger/Repositories/ICurrencyRepository.cs @@ -0,0 +1,11 @@ +using IO.Swagger.Models.dto; +using System.Threading.Tasks; + +namespace IO.Swagger.Repositories +{ + public interface ICurrencyRepository + { + Task CreateCurrency(CurrencyCreateBody request, int userId); + Task MintCurrency(CurrencyMintBody request, int userId); + } +} diff --git a/src/IO.Swagger/Services/BankDbContext.cs b/src/IO.Swagger/Services/BankDbContext.cs index 71e0528..48efb12 100644 --- a/src/IO.Swagger/Services/BankDbContext.cs +++ b/src/IO.Swagger/Services/BankDbContext.cs @@ -11,7 +11,44 @@ namespace IO.Swagger.Services } public DbSet Users { get; set; } + public DbSet Currencies { get; set; } + public DbSet Transactions { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + // currency -> user FK + modelBuilder.Entity() + .HasMany(u => u.Currencies) + .WithOne(c => c.User) + .HasForeignKey(c => c.UserId) + .HasPrincipalKey(u => u.Id) + .OnDelete(DeleteBehavior.NoAction); + + // transaction -> from user + modelBuilder.Entity() + .HasMany(u => u.TransactionsFrom) + .WithOne(t => t.FromUser) + .HasForeignKey(t => t.FromUserId) + .HasPrincipalKey(u => u.Id) + .OnDelete(DeleteBehavior.NoAction); + // transaction -> to user + modelBuilder.Entity() + .HasMany(u => u.TransactionsTo) + .WithOne(t => t.ToUser) + .HasForeignKey(t => t.ToUserId) + .HasPrincipalKey(u => u.Id) + .OnDelete(DeleteBehavior.NoAction); + // transaction -> currency + modelBuilder.Entity() + .HasOne(t => t.Currency) + .WithMany(c => c.Transactions) + .HasForeignKey(t => t.CurrencyId) + .HasPrincipalKey(c => c.CurrencyId) + .OnDelete(DeleteBehavior.NoAction); + + } } } diff --git a/src/IO.Swagger/Startup.cs b/src/IO.Swagger/Startup.cs index f514986..530da98 100644 --- a/src/IO.Swagger/Startup.cs +++ b/src/IO.Swagger/Startup.cs @@ -140,7 +140,7 @@ namespace IO.Swagger } Console.WriteLine(connectionString); services.AddScoped(); - //services.AddScoped(); + services.AddScoped(); services.AddDbContext(x => x.UseSqlServer(connectionString: connectionString)); services.AddSingleton(); }