Changeset d300631
- Timestamp:
- 04/28/26 14:53:32 (2 months ago)
- Branches:
- main
- Children:
- b373fea
- Parents:
- dc383dd
- Files:
-
- 1 added
- 6 edited
-
, (added)
-
ChapterX.API/appsettings.json (modified) (1 diff)
-
ChapterX.Application/Abstractions/IApplicationDbContext.cs (modified) (2 diffs)
-
ChapterX.Application/Auth/RegisterHandler.cs (modified) (3 diffs)
-
ChapterX.Application/Story/Commands/AddHandler.cs (modified) (3 diffs)
-
ChapterX.Infrastructure/Data/DataContext/ApplicationDbContext.cs (modified) (13 diffs)
-
ChapterX.Infrastructure/DependencyInjection.cs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
ChapterX.API/appsettings.json
rdc383dd rd300631 11 11 "Issuer": "ChapterX", 12 12 "Audience": "ChapterX" 13 }, 14 "ConnectionPool": { 15 "MinPoolSize": 1, 16 "MaxPoolSize": 20, 17 "ConnectionIdleLifetime": 300, 18 "ConnectionPruningInterval": 10, 19 "CommandTimeout": 30, 20 "Timeout": 15 13 21 } 14 22 } -
ChapterX.Application/Abstractions/IApplicationDbContext.cs
rdc383dd rd300631 1 1 using Microsoft.EntityFrameworkCore; 2 using Microsoft.EntityFrameworkCore.Storage; 2 3 using UserEntity = ChapterX.Domain.Entities.User; 3 4 using StoryEntity = ChapterX.Domain.Entities.Story; … … 40 41 DbSet<NeedApprovalEntity> NeedApprovals { get; } 41 42 Task<int> SaveChangesAsync(CancellationToken cancellationToken = default); 43 Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default); 42 44 } 43 45 } -
ChapterX.Application/Auth/RegisterHandler.cs
rdc383dd rd300631 1 using ChapterX.Application.Abstractions; 1 2 using ChapterX.Domain.Repositories; 2 3 using MediatR; … … 8 9 private readonly IUserRepository _userRepository; 9 10 private readonly IWriterRepository _writerRepository; 11 private readonly IApplicationDbContext _context; 10 12 11 public RegisterHandler(IUserRepository userRepository, IWriterRepository writerRepository )13 public RegisterHandler(IUserRepository userRepository, IWriterRepository writerRepository, IApplicationDbContext context) 12 14 { 13 15 _userRepository = userRepository; 14 16 _writerRepository = writerRepository; 17 _context = context; 15 18 } 16 19 … … 21 24 throw new InvalidOperationException("Email already in use."); 22 25 23 var user = new Domain.Entities.User 26 await using var transaction = await _context.BeginTransactionAsync(cancellationToken); 27 try 24 28 { 25 Username = request.Username, 26 Email = request.Email, 27 Name = request.Name, 28 Surname = request.Surname, 29 Password = BCrypt.Net.BCrypt.HashPassword(request.Password), 30 CreatedAt = DateTime.UtcNow, 31 UpdatedAt = DateTime.UtcNow 32 }; 29 var user = new Domain.Entities.User 30 { 31 Username = request.Username, 32 Email = request.Email, 33 Name = request.Name, 34 Surname = request.Surname, 35 Password = BCrypt.Net.BCrypt.HashPassword(request.Password), 36 CreatedAt = DateTime.UtcNow, 37 UpdatedAt = DateTime.UtcNow 38 }; 33 39 34 await _userRepository.AddAsync(user, cancellationToken);40 await _userRepository.AddAsync(user, cancellationToken); 35 41 36 var writer = new Domain.Entities.Writer { Id = user.Id };37 await _writerRepository.AddAsync(writer, cancellationToken);42 var writer = new Domain.Entities.Writer { Id = user.Id }; 43 await _writerRepository.AddAsync(writer, cancellationToken); 38 44 39 return new RegisterResponse(user.Id, user.Username, user.Email); 45 await transaction.CommitAsync(cancellationToken); 46 return new RegisterResponse(user.Id, user.Username, user.Email); 47 } 48 catch 49 { 50 await transaction.RollbackAsync(cancellationToken); 51 throw; 52 } 40 53 } 41 54 } -
ChapterX.Application/Story/Commands/AddHandler.cs
rdc383dd rd300631 1 using ChapterX.Application.Abstractions; 1 2 using ChapterX.Domain.Repositories; 2 3 using MediatR; … … 10 11 private readonly IGenreRepository _genreRepository; 11 12 private readonly IHasGenreRepository _hasGenreRepository; 13 private readonly IApplicationDbContext _context; 12 14 private readonly ILogger<AddHandler> _logger; 13 15 14 public AddHandler(IStoryRepository storyRepository, IGenreRepository genreRepository, IHasGenreRepository hasGenreRepository, I Logger<AddHandler> logger)16 public AddHandler(IStoryRepository storyRepository, IGenreRepository genreRepository, IHasGenreRepository hasGenreRepository, IApplicationDbContext context, ILogger<AddHandler> logger) 15 17 { 16 18 _storyRepository = storyRepository; 17 19 _genreRepository = genreRepository; 18 20 _hasGenreRepository = hasGenreRepository; 21 _context = context; 19 22 _logger = logger; 20 23 } … … 22 25 public async Task<AddResponse> Handle(AddRequest request, CancellationToken cancellationToken) 23 26 { 24 var story = new Domain.Entities.Story 27 await using var transaction = await _context.BeginTransactionAsync(cancellationToken); 28 try 25 29 { 26 MatureContent = request.MatureContent, 27 ShortDescription = request.ShortDescription, 28 Image = request.Image, 29 Content = request.Content, 30 UserId = request.UserId, 31 CreatedAt = DateTime.UtcNow, 32 UpdatedAt = DateTime.UtcNow 33 }; 30 var story = new Domain.Entities.Story 31 { 32 MatureContent = request.MatureContent, 33 ShortDescription = request.ShortDescription, 34 Image = request.Image, 35 Content = request.Content, 36 UserId = request.UserId, 37 CreatedAt = DateTime.UtcNow, 38 UpdatedAt = DateTime.UtcNow 39 }; 34 40 35 await _storyRepository.AddAsync(story, cancellationToken);41 await _storyRepository.AddAsync(story, cancellationToken); 36 42 37 foreach (var genreName in request.Genres ?? []) 43 foreach (var genreName in request.Genres ?? []) 44 { 45 var genre = await _genreRepository.GetByNameAsync(genreName, cancellationToken); 46 if (genre == null) continue; 47 await _hasGenreRepository.AddAsync(new Domain.Entities.HasGenre { StoryId = story.Id, GenreId = genre.Id }, cancellationToken); 48 } 49 50 await transaction.CommitAsync(cancellationToken); 51 return new AddResponse(story.Id); 52 } 53 catch 38 54 { 39 var genre = await _genreRepository.GetByNameAsync(genreName, cancellationToken); 40 if (genre == null) continue; 41 await _hasGenreRepository.AddAsync(new Domain.Entities.HasGenre { StoryId = story.Id, GenreId = genre.Id }, cancellationToken); 55 await transaction.RollbackAsync(cancellationToken); 56 throw; 42 57 } 43 44 return new AddResponse(story.Id);45 58 } 46 59 } -
ChapterX.Infrastructure/Data/DataContext/ApplicationDbContext.cs
rdc383dd rd300631 2 2 using ChapterX.Domain.Entities; 3 3 using Microsoft.EntityFrameworkCore; 4 using Microsoft.EntityFrameworkCore.Storage; 4 5 5 6 namespace ChapterX.Infrastructure.Data.DataContext … … 31 32 public DbSet<PermissionLevel> PermissionLevels { get; init; } 32 33 34 public Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default) 35 => Database.BeginTransactionAsync(cancellationToken); 36 33 37 protected override void OnModelCreating(ModelBuilder modelBuilder) 34 38 { … … 43 47 e.Property(x => x.Username).HasColumnName("username"); 44 48 e.Property(x => x.Email).HasColumnName("email"); 45 e.Property(x => x.Name).HasColumnName(" name");49 e.Property(x => x.Name).HasColumnName("user_name"); 46 50 e.Property(x => x.Surname).HasColumnName("surname"); 47 51 e.Property(x => x.Password).HasColumnName("password"); 48 e.Property(x => x.CreatedAt).HasColumnName(" created_at");49 e.Property(x => x.UpdatedAt).HasColumnName("u pdated_at");52 e.Property(x => x.CreatedAt).HasColumnName("user_created_at"); 53 e.Property(x => x.UpdatedAt).HasColumnName("user_updated_at"); 50 54 }); 51 55 … … 86 90 e.Property(x => x.ShortDescription).HasColumnName("short_description"); 87 91 e.Property(x => x.Image).HasColumnName("image"); 88 e.Property(x => x.Content).HasColumnName(" content");89 e.Property(x => x.UserId).HasColumnName("user_id"); 90 e.Property(x => x.CreatedAt).HasColumnName(" created_at");91 e.Property(x => x.UpdatedAt).HasColumnName(" updated_at");92 e.Property(x => x.Content).HasColumnName("story_content"); 93 e.Property(x => x.UserId).HasColumnName("user_id"); 94 e.Property(x => x.CreatedAt).HasColumnName("story_created_at"); 95 e.Property(x => x.UpdatedAt).HasColumnName("story_updated_at"); 92 96 e.HasOne(x => x.Writer).WithMany(w => w.Stories).HasForeignKey(x => x.UserId); 93 97 }); … … 113 117 e.Property(x => x.Name).HasColumnName("chapter_name"); 114 118 e.Property(x => x.Title).HasColumnName("title"); 115 e.Property(x => x.Content).HasColumnName("c ontent");119 e.Property(x => x.Content).HasColumnName("chapter_content"); 116 120 e.Property(x => x.WordCount).HasColumnName("word_count"); 117 121 e.Property(x => x.Rating).HasColumnName("rating"); … … 119 123 e.Property(x => x.ViewCount).HasColumnName("view_count"); 120 124 e.Property(x => x.StoryId).HasColumnName("story_id"); 121 e.Property(x => x.CreatedAt).HasColumnName("c reated_at");122 e.Property(x => x.UpdatedAt).HasColumnName(" updated_at");125 e.Property(x => x.CreatedAt).HasColumnName("chapter_created_at"); 126 e.Property(x => x.UpdatedAt).HasColumnName("chapter_updated_at"); 123 127 e.HasOne(x => x.Story).WithMany(s => s.Chapters).HasForeignKey(x => x.StoryId); 124 128 }); … … 130 134 e.HasKey(x => x.Id); 131 135 e.Property(x => x.Id).HasColumnName("genre_id"); 132 e.Property(x => x.Name).HasColumnName(" name");136 e.Property(x => x.Name).HasColumnName("genre_name"); 133 137 }); 134 138 … … 153 157 e.Property(x => x.UserId).HasColumnName("user_id"); 154 158 e.Property(x => x.StoryId).HasColumnName("story_id"); 155 e.Property(x => x.CreatedAt).HasColumnName(" created_at");159 e.Property(x => x.CreatedAt).HasColumnName("like_created_at"); 156 160 e.HasOne(x => x.User).WithMany(u => u.Likes).HasForeignKey(x => x.UserId); 157 161 e.HasOne(x => x.Story).WithMany(s => s.Likes).HasForeignKey(x => x.StoryId); … … 164 168 e.HasKey(x => x.Id); 165 169 e.Property(x => x.Id).HasColumnName("comment_id"); 166 e.Property(x => x.Content).HasColumnName("co ntent");167 e.Property(x => x.UserId).HasColumnName("user_id"); 168 e.Property(x => x.StoryId).HasColumnName("story_id"); 169 e.Property(x => x.CreatedAt).HasColumnName("c reated_at");170 e.Property(x => x.UpdatedAt).HasColumnName(" updated_at");170 e.Property(x => x.Content).HasColumnName("comment_content"); 171 e.Property(x => x.UserId).HasColumnName("user_id"); 172 e.Property(x => x.StoryId).HasColumnName("story_id"); 173 e.Property(x => x.CreatedAt).HasColumnName("comment_created_at"); 174 e.Property(x => x.UpdatedAt).HasColumnName("comment_updated_at"); 171 175 e.HasOne(x => x.User).WithMany(u => u.Comments).HasForeignKey(x => x.UserId); 172 176 e.HasOne(x => x.Story).WithMany(s => s.Comments).HasForeignKey(x => x.StoryId); … … 179 183 e.HasKey(x => x.Id); 180 184 e.Property(x => x.Id).HasColumnName("list_id"); 181 e.Property(x => x.Name).HasColumnName(" name");182 e.Property(x => x.Content).HasColumnName(" content");185 e.Property(x => x.Name).HasColumnName("list_name"); 186 e.Property(x => x.Content).HasColumnName("list_content"); 183 187 e.Property(x => x.IsPublic).HasColumnName("is_public"); 184 188 e.Property(x => x.UserId).HasColumnName("user_id"); … … 207 211 e.HasKey(x => x.Id); 208 212 e.Property(x => x.Id).HasColumnName("notification_id"); 209 e.Property(x => x.Content).HasColumnName(" content");213 e.Property(x => x.Content).HasColumnName("notification_content"); 210 214 e.Property(x => x.IsRead).HasColumnName("is_read"); 211 e.Property(x => x.CreatedAt).HasColumnName(" created_at");215 e.Property(x => x.CreatedAt).HasColumnName("notification_created_at"); 212 216 e.Property(x => x.RecipientUserId).HasColumnName("recipient_user_id"); 213 217 e.Property(x => x.Type).HasColumnName("type"); … … 249 253 e.Property(x => x.SuggestedText).HasColumnName("suggested_text"); 250 254 e.Property(x => x.Accepted).HasColumnName("accepted"); 251 e.Property(x => x.CreatedAt).HasColumnName(" created_at");255 e.Property(x => x.CreatedAt).HasColumnName("suggestion_created_at"); 252 256 e.Property(x => x.AppliedAt).HasColumnName("applied_at"); 253 257 e.Property(x => x.StoryId).HasColumnName("story_id"); … … 288 292 e.Property(x => x.UserId).HasColumnName("user_id"); 289 293 e.Property(x => x.StoryId).HasColumnName("story_id"); 290 e.Property(x => x.CreatedAt).HasColumnName("c reated_at");294 e.Property(x => x.CreatedAt).HasColumnName("collab_created_at"); 291 295 e.HasOne(x => x.User).WithMany(u => u.Collaborations).HasForeignKey(x => x.UserId); 292 296 e.HasOne(x => x.Story).WithMany(s => s.Collaborations).HasForeignKey(x => x.StoryId); -
ChapterX.Infrastructure/DependencyInjection.cs
rdc383dd rd300631 15 15 public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) 16 16 { 17 services.AddDbContext<ApplicationDbContext>(options => 18 options.UseNpgsql(configuration.GetConnectionString("Database"))); 17 var poolSection = configuration.GetSection("ConnectionPool"); 18 var minPoolSize = poolSection.GetValue<int>("MinPoolSize", 1); 19 var maxPoolSize = poolSection.GetValue<int>("MaxPoolSize", 20); 20 var idleLifetime = poolSection.GetValue<int>("ConnectionIdleLifetime", 300); 21 var pruningInterval = poolSection.GetValue<int>("ConnectionPruningInterval", 10); 22 var commandTimeout = poolSection.GetValue<int>("CommandTimeout", 30); 23 var connectionTimeout = poolSection.GetValue<int>("Timeout", 15); 24 25 var baseConnectionString = configuration.GetConnectionString("Database")!; 26 var connectionString = 27 $"{baseConnectionString};Minimum Pool Size={minPoolSize};Maximum Pool Size={maxPoolSize};" + 28 $"Connection Idle Lifetime={idleLifetime};Connection Pruning Interval={pruningInterval};" + 29 $"Command Timeout={commandTimeout};Timeout={connectionTimeout}"; 30 31 services.AddDbContextPool<ApplicationDbContext>(options => 32 options.UseNpgsql(connectionString)); 19 33 20 34 services.AddScoped<IApplicationDbContext>(sp => sp.GetRequiredService<ApplicationDbContext>());
Note:
See TracChangeset
for help on using the changeset viewer.
