├── .gitignore ├── Libraries ├── Portal.Application │ ├── Categories │ │ └── Queries │ │ │ └── Model │ │ │ └── CategoryDto.cs │ ├── Portal.Application.csproj │ └── System │ │ ├── ApplicationBuilderExtensions.cs │ │ ├── Mappings │ │ ├── IMapFrom.cs │ │ └── MappingProfile.cs │ │ └── ServiceCollectionExtensions.cs ├── Portal.Domain │ ├── Common │ │ ├── BaseEntity.cs │ │ ├── CommentStatus.cs │ │ ├── MaxLengthSize.cs │ │ └── MediaType.cs │ ├── Entities │ │ ├── Article.cs │ │ ├── ArticleCategory.cs │ │ ├── ArticleMedia.cs │ │ ├── Category.cs │ │ ├── Comment.cs │ │ ├── Contact.cs │ │ ├── Course.cs │ │ ├── CourseAction.cs │ │ ├── CourseLesson.cs │ │ ├── Media.cs │ │ ├── Poll.cs │ │ ├── PollAnswer.cs │ │ ├── PollVotingRecord.cs │ │ └── User.cs │ └── Portal.Domain.csproj ├── Portal.Infrastructure │ ├── Migrations │ │ ├── 20201111094609_First.Designer.cs │ │ ├── 20201111094609_First.cs │ │ └── PortalDbContextModelSnapshot.cs │ ├── Persistence │ │ ├── Configurations │ │ │ ├── Articles │ │ │ │ └── ArticleConfiguration.cs │ │ │ ├── Categories │ │ │ │ └── CategoryConfiguration.cs │ │ │ ├── Comments │ │ │ │ └── CommentConfiguration.cs │ │ │ ├── Contacts │ │ │ │ └── ContactConfiguration.cs │ │ │ ├── Courses │ │ │ │ ├── CourseActionConfiguration.cs │ │ │ │ ├── CourseConfiguration.cs │ │ │ │ └── CourseLessonConfiguratio.cs │ │ │ ├── Medias │ │ │ │ └── MediaConfiguration.cs │ │ │ ├── Polls │ │ │ │ ├── PollAnswerConfiguration.cs │ │ │ │ ├── PollConfiguration.cs │ │ │ │ └── PollVotingRecordConfiguration.cs │ │ │ └── Users │ │ │ │ └── UserConfiguration.cs │ │ ├── EntityFramework │ │ │ └── EfRepository.cs │ │ ├── IRepository.cs │ │ └── PortalDbContext.cs │ └── Portal.Infrastructure.csproj └── Portal.Shared │ ├── Portal.Shared.csproj │ └── Result │ ├── Result.cs │ ├── ResultSingle.cs │ └── Result{T}.cs ├── Portal-API.sln ├── Presentation └── Portal.API │ ├── Controllers │ └── HomeController.cs │ ├── Portal.API.csproj │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ └── appsettings.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /Libraries/Portal.Application/Categories/Queries/Model/CategoryDto.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Portal.Application.System.Mappings; 3 | using Portal.Domain.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace Portal.Application.Categories.Queries.Model 9 | { 10 | public class CategoryDto : IMapFrom 11 | { 12 | public int Id { get; set; } 13 | public string Name { get; set; } 14 | public string Description { get; set; } 15 | 16 | public void Mapping(Profile profile) 17 | { 18 | profile.CreateMap() 19 | .ForMember(c => c.Id, opt => opt.MapFrom(d => d.Id)) 20 | .ForMember(c => c.Description, opt => opt.MapFrom(d => d.Description)) 21 | .ForMember(c => c.Name, opt => opt.MapFrom(d => d.Name)); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Libraries/Portal.Application/Portal.Application.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Libraries/Portal.Application/System/ApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Portal.Application.System 7 | { 8 | public static class ApplicationBuilderExtensions 9 | { 10 | public static IApplicationBuilder ConfigSwagger(this IApplicationBuilder app) 11 | { 12 | app.UseSwagger(); 13 | app.UseSwaggerUI(c => 14 | { 15 | c.SwaggerEndpoint("/swagger/v1/swagger.json", "Portal API V1"); 16 | }); 17 | return app; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Libraries/Portal.Application/System/Mappings/IMapFrom.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Portal.Application.System.Mappings 7 | { 8 | public interface IMapFrom 9 | { 10 | void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType()); 11 | } 12 | } -------------------------------------------------------------------------------- /Libraries/Portal.Application/System/Mappings/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | namespace Portal.Application.System.Mappings 9 | { 10 | public class MappingProfile : Profile 11 | { 12 | public MappingProfile() 13 | { 14 | ApplyMappingsFormAssembly(Assembly.GetExecutingAssembly()); 15 | } 16 | 17 | private void ApplyMappingsFormAssembly(Assembly assembly) 18 | { 19 | var types = assembly.GetExportedTypes() 20 | .Where(t => t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>))) 21 | .ToList(); 22 | 23 | foreach (var type in types) 24 | { 25 | var instance = Activator.CreateInstance(type); 26 | var methodInfo = type.GetMethod("Mapping"); 27 | methodInfo?.Invoke(instance, new object[] { this }); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Libraries/Portal.Application/System/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.OpenApi.Models; 6 | using Portal.Infrastructure.Persistence; 7 | using Portal.Infrastructure.Persistence.EntityFramework; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Reflection; 11 | using System.Text; 12 | 13 | namespace Portal.Application.System 14 | { 15 | public static class ServiceCollectionExtensions 16 | { 17 | public static IServiceCollection InjectApplicationServices(this IServiceCollection services) 18 | { 19 | services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>)); 20 | return services; 21 | } 22 | 23 | public static IServiceCollection AddCustomizedDataStore(this IServiceCollection services, IConfiguration configuration) 24 | { 25 | services.AddDbContext(options => options.UseNpgsql(configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("Portal.Infrastructure"))); 26 | 27 | services.AddScoped(provider => provider.GetService()); 28 | return services; 29 | } 30 | 31 | public static IServiceCollection AddApplication(this IServiceCollection services) 32 | { 33 | services.AddAutoMapper(Assembly.GetExecutingAssembly()); 34 | return services; 35 | } 36 | 37 | public static IServiceCollection IntegrateSwagger(this IServiceCollection services, IConfiguration configuration) 38 | { 39 | services.AddSwaggerGen(options => 40 | { 41 | options.SwaggerDoc("v1", new OpenApiInfo 42 | { 43 | Title = configuration["Swagger:Title"], 44 | Version = configuration["Swagger:Version"], 45 | Description = configuration["Swagger:Description"] 46 | }); 47 | options.CustomSchemaIds(x => x.FullName); 48 | }); 49 | return services; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Common/BaseEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Portal.Domain.Common 4 | { 5 | public abstract class BaseEntity 6 | { 7 | public int Id { get; set; } 8 | 9 | public int CreatedBy { get; set; } 10 | 11 | public short IsActive { get; set; } = 1; 12 | 13 | public DateTime CreatedTime { get; set; } = DateTime.Now; 14 | 15 | public DateTime? UpdatedTime { get; set; } 16 | 17 | public int? UpdatedBy { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Common/CommentStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Portal.Domain.Common 2 | { 3 | public enum CommentStatus 4 | { 5 | Pending = 1, 6 | Approved = 5, 7 | NotApproved = 8 8 | } 9 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Common/MaxLengthSize.cs: -------------------------------------------------------------------------------- 1 | namespace Portal.Domain.Common 2 | { 3 | public enum MaxLengthSize 4 | { 5 | Title = 300, 6 | ShortDescription = 450, 7 | Description = 1500, 8 | Name = 150, 9 | EmailAddress = 150, 10 | MetaTitle = 160, 11 | MetaDescription = 255, 12 | PhoneNumber = 50, 13 | } 14 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Common/MediaType.cs: -------------------------------------------------------------------------------- 1 | namespace Portal.Domain.Common 2 | { 3 | public enum MediaType 4 | { 5 | Image = 1, 6 | File = 5, 7 | Video = 10 8 | } 9 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/Article.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class Article : BaseEntity 7 | { 8 | public string Title { get; set; } 9 | 10 | public string ShortDescription { get; set; } 11 | 12 | public string Description { get; set; } 13 | 14 | public int? ThumbnailImageId { get; set; } 15 | 16 | public virtual Media ThumbnailImage { get; set; } 17 | 18 | public int ReviewsCount { get; set; } 19 | 20 | public double RatingAverage { get; set; } 21 | 22 | public bool IsPublished { get; set; } 23 | 24 | public virtual ICollection ArticleMedias { get; set; } 25 | 26 | public virtual ICollection ArticleCategories { get; set; } 27 | 28 | public virtual ICollection Comments { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/ArticleCategory.cs: -------------------------------------------------------------------------------- 1 | namespace Portal.Domain.Entities 2 | { 3 | public class ArticleCategory 4 | { 5 | public int ArticleId { get; set; } 6 | 7 | public Article Article { get; set; } 8 | 9 | public int CategoryId { get; set; } 10 | 11 | public Category Category { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/ArticleMedia.cs: -------------------------------------------------------------------------------- 1 | namespace Portal.Domain.Entities 2 | { 3 | public class ArticleMedia 4 | { 5 | public int ArticleId { get; set; } 6 | 7 | public Article Article { get; set; } 8 | 9 | public int MediaId { get; set; } 10 | 11 | public Media Media { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/Category.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class Category : BaseEntity 7 | { 8 | public string Name { get; set; } 9 | 10 | public string MetaTitle { get; set; } 11 | 12 | public string MetaKeywords { get; set; } 13 | 14 | public string MetaDescription { get; set; } 15 | 16 | public string Description { get; set; } 17 | 18 | public int? ParentId { get; set; } 19 | 20 | public Category Parent { get; set; } 21 | 22 | public virtual ICollection ArticleCategories { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/Comment.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class Comment : BaseEntity 7 | { 8 | public int? UserId { get; set; } 9 | 10 | public virtual User User { get; set; } 11 | 12 | public int ArticleId { get; set; } 13 | 14 | public virtual Article Article { get; set; } 15 | 16 | public CommentStatus Status { get; set; } = CommentStatus.Pending; 17 | 18 | public string CommentText { get; set; } 19 | 20 | public string CommenterName { get; set; } 21 | 22 | public string CommenterEmail { get; set; } 23 | 24 | public int? ParentId { get; set; } 25 | 26 | public Comment Parent { get; set; } 27 | 28 | public IList Replies { get; protected set; } = new List(); 29 | } 30 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/Contact.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | 3 | namespace Portal.Domain.Entities 4 | { 5 | public class Contact : BaseEntity 6 | { 7 | public int? UserId { get; set; } 8 | 9 | public virtual User User { get; set; } 10 | 11 | public string FullName { get; set; } 12 | 13 | public string PhoneNumber { get; set; } 14 | 15 | public string EmailAddress { get; set; } 16 | 17 | public string Content { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/Course.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class Course : BaseEntity 7 | { 8 | public string Name { get; set; } 9 | 10 | public string ShortDescription { get; set; } 11 | 12 | public string Description { get; set; } 13 | 14 | public bool IsPublished { get; set; } 15 | 16 | public string MetaKeywords { get; set; } 17 | 18 | public string MetaDescription { get; set; } 19 | 20 | public string MetaTitle { get; set; } 21 | 22 | public virtual ICollection CourseLessons { get; set; } 23 | 24 | public virtual ICollection CourseActions { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/CourseAction.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | 3 | namespace Portal.Domain.Entities 4 | { 5 | public class CourseAction : BaseEntity 6 | { 7 | public int UserId { get; set; } 8 | 9 | public virtual User User { get; set; } 10 | 11 | public int CourseId { get; set; } 12 | 13 | public virtual Course Course { get; set; } 14 | 15 | public int CourseLessonId { get; set; } 16 | 17 | public virtual CourseLesson CourseLesson { get; set; } 18 | 19 | public bool Finished { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/CourseLesson.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class CourseLesson : BaseEntity 7 | { 8 | public string Name { get; set; } 9 | 10 | public string ShortDescription { get; set; } 11 | 12 | public string Description { get; set; } 13 | 14 | public int CourseId { get; set; } 15 | 16 | public virtual Course Course { get; set; } 17 | 18 | public virtual ICollection CourseActions { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/Media.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class Media : BaseEntity 7 | { 8 | public string Caption { get; set; } 9 | 10 | public int FileSize { get; set; } 11 | 12 | public string FileName { get; set; } 13 | 14 | public MediaType MediaType { get; set; } 15 | 16 | public virtual ICollection ArticleMedias { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/Poll.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Portal.Domain.Entities 6 | { 7 | public class Poll : BaseEntity 8 | { 9 | public string Name { get; set; } 10 | 11 | public bool ShowOnHomePage { get; set; } 12 | 13 | public bool AllowGuestsToVote { get; set; } 14 | 15 | public DateTime StartDate { get; set; } 16 | 17 | public DateTime? EndDate { get; set; } 18 | 19 | public virtual ICollection PollAnswers { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/PollAnswer.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class PollAnswer : BaseEntity 7 | { 8 | public int PollId { get; set; } 9 | 10 | public virtual Poll Poll { get; set; } 11 | 12 | public string Name { get; set; } 13 | 14 | public int DisplayOrder { get; set; } 15 | 16 | public virtual ICollection PollVotingRecords { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/PollVotingRecord.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | 3 | namespace Portal.Domain.Entities 4 | { 5 | public class PollVotingRecord : BaseEntity 6 | { 7 | public int PollAnswerId { get; set; } 8 | 9 | public virtual PollAnswer PollAnswer { get; set; } 10 | 11 | public int PollId { get; set; } 12 | 13 | public int? UserId { get; set; } 14 | 15 | public virtual User User { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Entities/User.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System.Collections.Generic; 3 | 4 | namespace Portal.Domain.Entities 5 | { 6 | public class User : BaseEntity 7 | { 8 | public string FullName { get; set; } 9 | 10 | public string Email { get; set; } 11 | 12 | public bool IsDeleted { get; set; } 13 | 14 | public virtual ICollection
Articles { get; set; } 15 | 16 | public virtual ICollection Comments { get; set; } 17 | 18 | public virtual ICollection Contacts { get; set; } 19 | 20 | public virtual ICollection CourseActions { get; set; } 21 | 22 | public virtual ICollection PollVotingRecords { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /Libraries/Portal.Domain/Portal.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Migrations/20201111094609_First.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 8 | using Portal.Infrastructure.Persistence; 9 | 10 | namespace Portal.Infrastructure.Migrations 11 | { 12 | [DbContext(typeof(PortalDbContext))] 13 | [Migration("20201111094609_First")] 14 | partial class First 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) 21 | .HasAnnotation("ProductVersion", "3.1.9") 22 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 23 | 24 | modelBuilder.Entity("Portal.Domain.Entities.Article", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("integer") 29 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 30 | 31 | b.Property("CreatedBy") 32 | .HasColumnType("integer"); 33 | 34 | b.Property("CreatedTime") 35 | .HasColumnType("timestamp without time zone"); 36 | 37 | b.Property("Description") 38 | .IsRequired() 39 | .HasColumnType("character varying(1500)") 40 | .HasMaxLength(1500); 41 | 42 | b.Property("IsActive") 43 | .HasColumnType("smallint"); 44 | 45 | b.Property("IsPublished") 46 | .HasColumnType("boolean"); 47 | 48 | b.Property("RatingAverage") 49 | .HasColumnType("double precision"); 50 | 51 | b.Property("ReviewsCount") 52 | .HasColumnType("integer"); 53 | 54 | b.Property("ShortDescription") 55 | .IsRequired() 56 | .HasColumnType("character varying(450)") 57 | .HasMaxLength(450); 58 | 59 | b.Property("ThumbnailImageId") 60 | .HasColumnType("integer"); 61 | 62 | b.Property("Title") 63 | .IsRequired() 64 | .HasColumnType("character varying(300)") 65 | .HasMaxLength(300); 66 | 67 | b.Property("UpdatedBy") 68 | .HasColumnType("integer"); 69 | 70 | b.Property("UpdatedTime") 71 | .HasColumnType("timestamp without time zone"); 72 | 73 | b.Property("UserId") 74 | .HasColumnType("integer"); 75 | 76 | b.HasKey("Id"); 77 | 78 | b.HasIndex("ThumbnailImageId"); 79 | 80 | b.HasIndex("UserId"); 81 | 82 | b.ToTable("Article"); 83 | }); 84 | 85 | modelBuilder.Entity("Portal.Domain.Entities.ArticleCategory", b => 86 | { 87 | b.Property("ArticleId") 88 | .HasColumnType("integer"); 89 | 90 | b.Property("CategoryId") 91 | .HasColumnType("integer"); 92 | 93 | b.HasKey("ArticleId", "CategoryId"); 94 | 95 | b.HasIndex("CategoryId"); 96 | 97 | b.ToTable("ArticleCategory"); 98 | }); 99 | 100 | modelBuilder.Entity("Portal.Domain.Entities.ArticleMedia", b => 101 | { 102 | b.Property("ArticleId") 103 | .HasColumnType("integer"); 104 | 105 | b.Property("MediaId") 106 | .HasColumnType("integer"); 107 | 108 | b.HasKey("ArticleId", "MediaId"); 109 | 110 | b.HasIndex("MediaId"); 111 | 112 | b.ToTable("ArticleMedia"); 113 | }); 114 | 115 | modelBuilder.Entity("Portal.Domain.Entities.Category", b => 116 | { 117 | b.Property("Id") 118 | .ValueGeneratedOnAdd() 119 | .HasColumnType("integer") 120 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 121 | 122 | b.Property("CreatedBy") 123 | .HasColumnType("integer"); 124 | 125 | b.Property("CreatedTime") 126 | .HasColumnType("timestamp without time zone"); 127 | 128 | b.Property("Description") 129 | .IsRequired() 130 | .HasColumnType("character varying(1500)") 131 | .HasMaxLength(1500); 132 | 133 | b.Property("IsActive") 134 | .HasColumnType("smallint"); 135 | 136 | b.Property("MetaDescription") 137 | .IsRequired() 138 | .HasColumnType("character varying(255)") 139 | .HasMaxLength(255); 140 | 141 | b.Property("MetaKeywords") 142 | .IsRequired() 143 | .HasColumnType("character varying(255)") 144 | .HasMaxLength(255); 145 | 146 | b.Property("MetaTitle") 147 | .IsRequired() 148 | .HasColumnType("character varying(160)") 149 | .HasMaxLength(160); 150 | 151 | b.Property("Name") 152 | .IsRequired() 153 | .HasColumnType("character varying(150)") 154 | .HasMaxLength(150); 155 | 156 | b.Property("ParentId") 157 | .HasColumnType("integer"); 158 | 159 | b.Property("UpdatedBy") 160 | .HasColumnType("integer"); 161 | 162 | b.Property("UpdatedTime") 163 | .HasColumnType("timestamp without time zone"); 164 | 165 | b.HasKey("Id"); 166 | 167 | b.HasIndex("Name") 168 | .IsUnique(); 169 | 170 | b.HasIndex("ParentId"); 171 | 172 | b.ToTable("Category"); 173 | }); 174 | 175 | modelBuilder.Entity("Portal.Domain.Entities.Comment", b => 176 | { 177 | b.Property("Id") 178 | .ValueGeneratedOnAdd() 179 | .HasColumnType("integer") 180 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 181 | 182 | b.Property("ArticleId") 183 | .HasColumnType("integer"); 184 | 185 | b.Property("CommentText") 186 | .IsRequired() 187 | .HasColumnType("character varying(1500)") 188 | .HasMaxLength(1500); 189 | 190 | b.Property("CommenterEmail") 191 | .IsRequired() 192 | .HasColumnType("character varying(150)") 193 | .HasMaxLength(150); 194 | 195 | b.Property("CommenterName") 196 | .IsRequired() 197 | .HasColumnType("character varying(150)") 198 | .HasMaxLength(150); 199 | 200 | b.Property("CreatedBy") 201 | .HasColumnType("integer"); 202 | 203 | b.Property("CreatedTime") 204 | .HasColumnType("timestamp without time zone"); 205 | 206 | b.Property("IsActive") 207 | .HasColumnType("smallint"); 208 | 209 | b.Property("ParentId") 210 | .HasColumnType("integer"); 211 | 212 | b.Property("Status") 213 | .HasColumnType("integer"); 214 | 215 | b.Property("UpdatedBy") 216 | .HasColumnType("integer"); 217 | 218 | b.Property("UpdatedTime") 219 | .HasColumnType("timestamp without time zone"); 220 | 221 | b.Property("UserId") 222 | .HasColumnType("integer"); 223 | 224 | b.HasKey("Id"); 225 | 226 | b.HasIndex("ArticleId"); 227 | 228 | b.HasIndex("ParentId"); 229 | 230 | b.HasIndex("UserId"); 231 | 232 | b.ToTable("Comment"); 233 | }); 234 | 235 | modelBuilder.Entity("Portal.Domain.Entities.Contact", b => 236 | { 237 | b.Property("Id") 238 | .ValueGeneratedOnAdd() 239 | .HasColumnType("integer") 240 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 241 | 242 | b.Property("Content") 243 | .IsRequired() 244 | .HasColumnType("character varying(1500)") 245 | .HasMaxLength(1500); 246 | 247 | b.Property("CreatedBy") 248 | .HasColumnType("integer"); 249 | 250 | b.Property("CreatedTime") 251 | .HasColumnType("timestamp without time zone"); 252 | 253 | b.Property("EmailAddress") 254 | .IsRequired() 255 | .HasColumnType("character varying(150)") 256 | .HasMaxLength(150); 257 | 258 | b.Property("FullName") 259 | .IsRequired() 260 | .HasColumnType("character varying(150)") 261 | .HasMaxLength(150); 262 | 263 | b.Property("IsActive") 264 | .HasColumnType("smallint"); 265 | 266 | b.Property("PhoneNumber") 267 | .IsRequired() 268 | .HasColumnType("character varying(50)") 269 | .HasMaxLength(50); 270 | 271 | b.Property("UpdatedBy") 272 | .HasColumnType("integer"); 273 | 274 | b.Property("UpdatedTime") 275 | .HasColumnType("timestamp without time zone"); 276 | 277 | b.Property("UserId") 278 | .HasColumnType("integer"); 279 | 280 | b.HasKey("Id"); 281 | 282 | b.HasIndex("UserId"); 283 | 284 | b.ToTable("Contact"); 285 | }); 286 | 287 | modelBuilder.Entity("Portal.Domain.Entities.Course", b => 288 | { 289 | b.Property("Id") 290 | .ValueGeneratedOnAdd() 291 | .HasColumnType("integer") 292 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 293 | 294 | b.Property("CreatedBy") 295 | .HasColumnType("integer"); 296 | 297 | b.Property("CreatedTime") 298 | .HasColumnType("timestamp without time zone"); 299 | 300 | b.Property("Description") 301 | .IsRequired() 302 | .HasColumnType("character varying(1500)") 303 | .HasMaxLength(1500); 304 | 305 | b.Property("IsActive") 306 | .HasColumnType("smallint"); 307 | 308 | b.Property("IsPublished") 309 | .HasColumnType("boolean"); 310 | 311 | b.Property("MetaDescription") 312 | .IsRequired() 313 | .HasColumnType("character varying(255)") 314 | .HasMaxLength(255); 315 | 316 | b.Property("MetaKeywords") 317 | .IsRequired() 318 | .HasColumnType("character varying(255)") 319 | .HasMaxLength(255); 320 | 321 | b.Property("MetaTitle") 322 | .IsRequired() 323 | .HasColumnType("character varying(160)") 324 | .HasMaxLength(160); 325 | 326 | b.Property("Name") 327 | .IsRequired() 328 | .HasColumnType("character varying(150)") 329 | .HasMaxLength(150); 330 | 331 | b.Property("ShortDescription") 332 | .IsRequired() 333 | .HasColumnType("character varying(450)") 334 | .HasMaxLength(450); 335 | 336 | b.Property("UpdatedBy") 337 | .HasColumnType("integer"); 338 | 339 | b.Property("UpdatedTime") 340 | .HasColumnType("timestamp without time zone"); 341 | 342 | b.HasKey("Id"); 343 | 344 | b.ToTable("Course"); 345 | }); 346 | 347 | modelBuilder.Entity("Portal.Domain.Entities.CourseAction", b => 348 | { 349 | b.Property("Id") 350 | .ValueGeneratedOnAdd() 351 | .HasColumnType("integer") 352 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 353 | 354 | b.Property("CourseId") 355 | .HasColumnType("integer"); 356 | 357 | b.Property("CourseLessonId") 358 | .HasColumnType("integer"); 359 | 360 | b.Property("CreatedBy") 361 | .HasColumnType("integer"); 362 | 363 | b.Property("CreatedTime") 364 | .HasColumnType("timestamp without time zone"); 365 | 366 | b.Property("Finished") 367 | .HasColumnType("boolean"); 368 | 369 | b.Property("IsActive") 370 | .HasColumnType("smallint"); 371 | 372 | b.Property("UpdatedBy") 373 | .HasColumnType("integer"); 374 | 375 | b.Property("UpdatedTime") 376 | .HasColumnType("timestamp without time zone"); 377 | 378 | b.Property("UserId") 379 | .HasColumnType("integer"); 380 | 381 | b.HasKey("Id"); 382 | 383 | b.HasIndex("CourseId"); 384 | 385 | b.HasIndex("CourseLessonId"); 386 | 387 | b.HasIndex("UserId"); 388 | 389 | b.ToTable("CourseAction"); 390 | }); 391 | 392 | modelBuilder.Entity("Portal.Domain.Entities.CourseLesson", b => 393 | { 394 | b.Property("Id") 395 | .ValueGeneratedOnAdd() 396 | .HasColumnType("integer") 397 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 398 | 399 | b.Property("CourseId") 400 | .HasColumnType("integer"); 401 | 402 | b.Property("CreatedBy") 403 | .HasColumnType("integer"); 404 | 405 | b.Property("CreatedTime") 406 | .HasColumnType("timestamp without time zone"); 407 | 408 | b.Property("Description") 409 | .IsRequired() 410 | .HasColumnType("character varying(1500)") 411 | .HasMaxLength(1500); 412 | 413 | b.Property("IsActive") 414 | .HasColumnType("smallint"); 415 | 416 | b.Property("Name") 417 | .IsRequired() 418 | .HasColumnType("character varying(150)") 419 | .HasMaxLength(150); 420 | 421 | b.Property("ShortDescription") 422 | .IsRequired() 423 | .HasColumnType("character varying(450)") 424 | .HasMaxLength(450); 425 | 426 | b.Property("UpdatedBy") 427 | .HasColumnType("integer"); 428 | 429 | b.Property("UpdatedTime") 430 | .HasColumnType("timestamp without time zone"); 431 | 432 | b.HasKey("Id"); 433 | 434 | b.HasIndex("CourseId"); 435 | 436 | b.ToTable("CourseLesson"); 437 | }); 438 | 439 | modelBuilder.Entity("Portal.Domain.Entities.Media", b => 440 | { 441 | b.Property("Id") 442 | .ValueGeneratedOnAdd() 443 | .HasColumnType("integer") 444 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 445 | 446 | b.Property("Caption") 447 | .IsRequired() 448 | .HasColumnType("character varying(150)") 449 | .HasMaxLength(150); 450 | 451 | b.Property("CreatedBy") 452 | .HasColumnType("integer"); 453 | 454 | b.Property("CreatedTime") 455 | .HasColumnType("timestamp without time zone"); 456 | 457 | b.Property("FileName") 458 | .IsRequired() 459 | .HasColumnType("character varying(150)") 460 | .HasMaxLength(150); 461 | 462 | b.Property("FileSize") 463 | .HasColumnType("integer"); 464 | 465 | b.Property("IsActive") 466 | .HasColumnType("smallint"); 467 | 468 | b.Property("MediaType") 469 | .HasColumnType("integer"); 470 | 471 | b.Property("UpdatedBy") 472 | .HasColumnType("integer"); 473 | 474 | b.Property("UpdatedTime") 475 | .HasColumnType("timestamp without time zone"); 476 | 477 | b.HasKey("Id"); 478 | 479 | b.ToTable("Media"); 480 | }); 481 | 482 | modelBuilder.Entity("Portal.Domain.Entities.Poll", b => 483 | { 484 | b.Property("Id") 485 | .ValueGeneratedOnAdd() 486 | .HasColumnType("integer") 487 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 488 | 489 | b.Property("AllowGuestsToVote") 490 | .HasColumnType("boolean"); 491 | 492 | b.Property("CreatedBy") 493 | .HasColumnType("integer"); 494 | 495 | b.Property("CreatedTime") 496 | .HasColumnType("timestamp without time zone"); 497 | 498 | b.Property("EndDate") 499 | .HasColumnType("timestamp without time zone"); 500 | 501 | b.Property("IsActive") 502 | .HasColumnType("smallint"); 503 | 504 | b.Property("Name") 505 | .IsRequired() 506 | .HasColumnType("character varying(150)") 507 | .HasMaxLength(150); 508 | 509 | b.Property("ShowOnHomePage") 510 | .HasColumnType("boolean"); 511 | 512 | b.Property("StartDate") 513 | .HasColumnType("timestamp without time zone"); 514 | 515 | b.Property("UpdatedBy") 516 | .HasColumnType("integer"); 517 | 518 | b.Property("UpdatedTime") 519 | .HasColumnType("timestamp without time zone"); 520 | 521 | b.HasKey("Id"); 522 | 523 | b.ToTable("Poll"); 524 | }); 525 | 526 | modelBuilder.Entity("Portal.Domain.Entities.PollAnswer", b => 527 | { 528 | b.Property("Id") 529 | .ValueGeneratedOnAdd() 530 | .HasColumnType("integer") 531 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 532 | 533 | b.Property("CreatedBy") 534 | .HasColumnType("integer"); 535 | 536 | b.Property("CreatedTime") 537 | .HasColumnType("timestamp without time zone"); 538 | 539 | b.Property("DisplayOrder") 540 | .HasColumnType("integer"); 541 | 542 | b.Property("IsActive") 543 | .HasColumnType("smallint"); 544 | 545 | b.Property("Name") 546 | .IsRequired() 547 | .HasColumnType("character varying(150)") 548 | .HasMaxLength(150); 549 | 550 | b.Property("PollId") 551 | .HasColumnType("integer"); 552 | 553 | b.Property("UpdatedBy") 554 | .HasColumnType("integer"); 555 | 556 | b.Property("UpdatedTime") 557 | .HasColumnType("timestamp without time zone"); 558 | 559 | b.HasKey("Id"); 560 | 561 | b.HasIndex("PollId"); 562 | 563 | b.ToTable("PollAnswer"); 564 | }); 565 | 566 | modelBuilder.Entity("Portal.Domain.Entities.PollVotingRecord", b => 567 | { 568 | b.Property("Id") 569 | .ValueGeneratedOnAdd() 570 | .HasColumnType("integer") 571 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 572 | 573 | b.Property("CreatedBy") 574 | .HasColumnType("integer"); 575 | 576 | b.Property("CreatedTime") 577 | .HasColumnType("timestamp without time zone"); 578 | 579 | b.Property("IsActive") 580 | .HasColumnType("smallint"); 581 | 582 | b.Property("PollAnswerId") 583 | .HasColumnType("integer"); 584 | 585 | b.Property("PollId") 586 | .HasColumnType("integer"); 587 | 588 | b.Property("UpdatedBy") 589 | .HasColumnType("integer"); 590 | 591 | b.Property("UpdatedTime") 592 | .HasColumnType("timestamp without time zone"); 593 | 594 | b.Property("UserId") 595 | .HasColumnType("integer"); 596 | 597 | b.HasKey("Id"); 598 | 599 | b.HasIndex("PollAnswerId"); 600 | 601 | b.HasIndex("UserId"); 602 | 603 | b.ToTable("PollVotingRecord"); 604 | }); 605 | 606 | modelBuilder.Entity("Portal.Domain.Entities.User", b => 607 | { 608 | b.Property("Id") 609 | .ValueGeneratedOnAdd() 610 | .HasColumnType("integer") 611 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 612 | 613 | b.Property("CreatedBy") 614 | .HasColumnType("integer"); 615 | 616 | b.Property("CreatedTime") 617 | .HasColumnType("timestamp without time zone"); 618 | 619 | b.Property("Email") 620 | .IsRequired() 621 | .HasColumnType("character varying(150)") 622 | .HasMaxLength(150); 623 | 624 | b.Property("FullName") 625 | .IsRequired() 626 | .HasColumnType("character varying(150)") 627 | .HasMaxLength(150); 628 | 629 | b.Property("IsActive") 630 | .HasColumnType("smallint"); 631 | 632 | b.Property("IsDeleted") 633 | .HasColumnType("boolean"); 634 | 635 | b.Property("UpdatedBy") 636 | .HasColumnType("integer"); 637 | 638 | b.Property("UpdatedTime") 639 | .HasColumnType("timestamp without time zone"); 640 | 641 | b.HasKey("Id"); 642 | 643 | b.HasIndex("Email") 644 | .IsUnique(); 645 | 646 | b.ToTable("User"); 647 | }); 648 | 649 | modelBuilder.Entity("Portal.Domain.Entities.Article", b => 650 | { 651 | b.HasOne("Portal.Domain.Entities.Media", "ThumbnailImage") 652 | .WithMany() 653 | .HasForeignKey("ThumbnailImageId"); 654 | 655 | b.HasOne("Portal.Domain.Entities.User", null) 656 | .WithMany("Articles") 657 | .HasForeignKey("UserId"); 658 | }); 659 | 660 | modelBuilder.Entity("Portal.Domain.Entities.ArticleCategory", b => 661 | { 662 | b.HasOne("Portal.Domain.Entities.Article", "Article") 663 | .WithMany("ArticleCategories") 664 | .HasForeignKey("ArticleId") 665 | .OnDelete(DeleteBehavior.Cascade) 666 | .IsRequired(); 667 | 668 | b.HasOne("Portal.Domain.Entities.Category", "Category") 669 | .WithMany("ArticleCategories") 670 | .HasForeignKey("CategoryId") 671 | .OnDelete(DeleteBehavior.Cascade) 672 | .IsRequired(); 673 | }); 674 | 675 | modelBuilder.Entity("Portal.Domain.Entities.ArticleMedia", b => 676 | { 677 | b.HasOne("Portal.Domain.Entities.Article", "Article") 678 | .WithMany("ArticleMedias") 679 | .HasForeignKey("ArticleId") 680 | .OnDelete(DeleteBehavior.Cascade) 681 | .IsRequired(); 682 | 683 | b.HasOne("Portal.Domain.Entities.Media", "Media") 684 | .WithMany("ArticleMedias") 685 | .HasForeignKey("MediaId") 686 | .OnDelete(DeleteBehavior.Cascade) 687 | .IsRequired(); 688 | }); 689 | 690 | modelBuilder.Entity("Portal.Domain.Entities.Category", b => 691 | { 692 | b.HasOne("Portal.Domain.Entities.Category", "Parent") 693 | .WithMany() 694 | .HasForeignKey("ParentId"); 695 | }); 696 | 697 | modelBuilder.Entity("Portal.Domain.Entities.Comment", b => 698 | { 699 | b.HasOne("Portal.Domain.Entities.Article", "Article") 700 | .WithMany("Comments") 701 | .HasForeignKey("ArticleId") 702 | .OnDelete(DeleteBehavior.Cascade) 703 | .IsRequired(); 704 | 705 | b.HasOne("Portal.Domain.Entities.Comment", "Parent") 706 | .WithMany("Replies") 707 | .HasForeignKey("ParentId"); 708 | 709 | b.HasOne("Portal.Domain.Entities.User", "User") 710 | .WithMany("Comments") 711 | .HasForeignKey("UserId"); 712 | }); 713 | 714 | modelBuilder.Entity("Portal.Domain.Entities.Contact", b => 715 | { 716 | b.HasOne("Portal.Domain.Entities.User", "User") 717 | .WithMany("Contacts") 718 | .HasForeignKey("UserId"); 719 | }); 720 | 721 | modelBuilder.Entity("Portal.Domain.Entities.CourseAction", b => 722 | { 723 | b.HasOne("Portal.Domain.Entities.Course", "Course") 724 | .WithMany("CourseActions") 725 | .HasForeignKey("CourseId") 726 | .OnDelete(DeleteBehavior.Cascade) 727 | .IsRequired(); 728 | 729 | b.HasOne("Portal.Domain.Entities.CourseLesson", "CourseLesson") 730 | .WithMany("CourseActions") 731 | .HasForeignKey("CourseLessonId") 732 | .OnDelete(DeleteBehavior.Cascade) 733 | .IsRequired(); 734 | 735 | b.HasOne("Portal.Domain.Entities.User", "User") 736 | .WithMany("CourseActions") 737 | .HasForeignKey("UserId") 738 | .OnDelete(DeleteBehavior.Cascade) 739 | .IsRequired(); 740 | }); 741 | 742 | modelBuilder.Entity("Portal.Domain.Entities.CourseLesson", b => 743 | { 744 | b.HasOne("Portal.Domain.Entities.Course", "Course") 745 | .WithMany("CourseLessons") 746 | .HasForeignKey("CourseId") 747 | .OnDelete(DeleteBehavior.Cascade) 748 | .IsRequired(); 749 | }); 750 | 751 | modelBuilder.Entity("Portal.Domain.Entities.PollAnswer", b => 752 | { 753 | b.HasOne("Portal.Domain.Entities.Poll", "Poll") 754 | .WithMany("PollAnswers") 755 | .HasForeignKey("PollId") 756 | .OnDelete(DeleteBehavior.Cascade) 757 | .IsRequired(); 758 | }); 759 | 760 | modelBuilder.Entity("Portal.Domain.Entities.PollVotingRecord", b => 761 | { 762 | b.HasOne("Portal.Domain.Entities.PollAnswer", "PollAnswer") 763 | .WithMany("PollVotingRecords") 764 | .HasForeignKey("PollAnswerId") 765 | .OnDelete(DeleteBehavior.Cascade) 766 | .IsRequired(); 767 | 768 | b.HasOne("Portal.Domain.Entities.User", "User") 769 | .WithMany("PollVotingRecords") 770 | .HasForeignKey("UserId"); 771 | }); 772 | #pragma warning restore 612, 618 773 | } 774 | } 775 | } 776 | -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Migrations/20201111094609_First.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 4 | 5 | namespace Portal.Infrastructure.Migrations 6 | { 7 | public partial class First : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Category", 13 | columns: table => new 14 | { 15 | Id = table.Column(nullable: false) 16 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 17 | CreatedBy = table.Column(nullable: false), 18 | IsActive = table.Column(nullable: false), 19 | CreatedTime = table.Column(nullable: false), 20 | UpdatedTime = table.Column(nullable: true), 21 | UpdatedBy = table.Column(nullable: true), 22 | Name = table.Column(maxLength: 150, nullable: false), 23 | MetaTitle = table.Column(maxLength: 160, nullable: false), 24 | MetaKeywords = table.Column(maxLength: 255, nullable: false), 25 | MetaDescription = table.Column(maxLength: 255, nullable: false), 26 | Description = table.Column(maxLength: 1500, nullable: false), 27 | ParentId = table.Column(nullable: true) 28 | }, 29 | constraints: table => 30 | { 31 | table.PrimaryKey("PK_Category", x => x.Id); 32 | table.ForeignKey( 33 | name: "FK_Category_Category_ParentId", 34 | column: x => x.ParentId, 35 | principalTable: "Category", 36 | principalColumn: "Id", 37 | onDelete: ReferentialAction.Restrict); 38 | }); 39 | 40 | migrationBuilder.CreateTable( 41 | name: "Course", 42 | columns: table => new 43 | { 44 | Id = table.Column(nullable: false) 45 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 46 | CreatedBy = table.Column(nullable: false), 47 | IsActive = table.Column(nullable: false), 48 | CreatedTime = table.Column(nullable: false), 49 | UpdatedTime = table.Column(nullable: true), 50 | UpdatedBy = table.Column(nullable: true), 51 | Name = table.Column(maxLength: 150, nullable: false), 52 | ShortDescription = table.Column(maxLength: 450, nullable: false), 53 | Description = table.Column(maxLength: 1500, nullable: false), 54 | IsPublished = table.Column(nullable: false), 55 | MetaKeywords = table.Column(maxLength: 255, nullable: false), 56 | MetaDescription = table.Column(maxLength: 255, nullable: false), 57 | MetaTitle = table.Column(maxLength: 160, nullable: false) 58 | }, 59 | constraints: table => 60 | { 61 | table.PrimaryKey("PK_Course", x => x.Id); 62 | }); 63 | 64 | migrationBuilder.CreateTable( 65 | name: "Media", 66 | columns: table => new 67 | { 68 | Id = table.Column(nullable: false) 69 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 70 | CreatedBy = table.Column(nullable: false), 71 | IsActive = table.Column(nullable: false), 72 | CreatedTime = table.Column(nullable: false), 73 | UpdatedTime = table.Column(nullable: true), 74 | UpdatedBy = table.Column(nullable: true), 75 | Caption = table.Column(maxLength: 150, nullable: false), 76 | FileSize = table.Column(nullable: false), 77 | FileName = table.Column(maxLength: 150, nullable: false), 78 | MediaType = table.Column(nullable: false) 79 | }, 80 | constraints: table => 81 | { 82 | table.PrimaryKey("PK_Media", x => x.Id); 83 | }); 84 | 85 | migrationBuilder.CreateTable( 86 | name: "Poll", 87 | columns: table => new 88 | { 89 | Id = table.Column(nullable: false) 90 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 91 | CreatedBy = table.Column(nullable: false), 92 | IsActive = table.Column(nullable: false), 93 | CreatedTime = table.Column(nullable: false), 94 | UpdatedTime = table.Column(nullable: true), 95 | UpdatedBy = table.Column(nullable: true), 96 | Name = table.Column(maxLength: 150, nullable: false), 97 | ShowOnHomePage = table.Column(nullable: false), 98 | AllowGuestsToVote = table.Column(nullable: false), 99 | StartDate = table.Column(nullable: false), 100 | EndDate = table.Column(nullable: true) 101 | }, 102 | constraints: table => 103 | { 104 | table.PrimaryKey("PK_Poll", x => x.Id); 105 | }); 106 | 107 | migrationBuilder.CreateTable( 108 | name: "User", 109 | columns: table => new 110 | { 111 | Id = table.Column(nullable: false) 112 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 113 | CreatedBy = table.Column(nullable: false), 114 | IsActive = table.Column(nullable: false), 115 | CreatedTime = table.Column(nullable: false), 116 | UpdatedTime = table.Column(nullable: true), 117 | UpdatedBy = table.Column(nullable: true), 118 | FullName = table.Column(maxLength: 150, nullable: false), 119 | Email = table.Column(maxLength: 150, nullable: false), 120 | IsDeleted = table.Column(nullable: false) 121 | }, 122 | constraints: table => 123 | { 124 | table.PrimaryKey("PK_User", x => x.Id); 125 | }); 126 | 127 | migrationBuilder.CreateTable( 128 | name: "CourseLesson", 129 | columns: table => new 130 | { 131 | Id = table.Column(nullable: false) 132 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 133 | CreatedBy = table.Column(nullable: false), 134 | IsActive = table.Column(nullable: false), 135 | CreatedTime = table.Column(nullable: false), 136 | UpdatedTime = table.Column(nullable: true), 137 | UpdatedBy = table.Column(nullable: true), 138 | Name = table.Column(maxLength: 150, nullable: false), 139 | ShortDescription = table.Column(maxLength: 450, nullable: false), 140 | Description = table.Column(maxLength: 1500, nullable: false), 141 | CourseId = table.Column(nullable: false) 142 | }, 143 | constraints: table => 144 | { 145 | table.PrimaryKey("PK_CourseLesson", x => x.Id); 146 | table.ForeignKey( 147 | name: "FK_CourseLesson_Course_CourseId", 148 | column: x => x.CourseId, 149 | principalTable: "Course", 150 | principalColumn: "Id", 151 | onDelete: ReferentialAction.Cascade); 152 | }); 153 | 154 | migrationBuilder.CreateTable( 155 | name: "PollAnswer", 156 | columns: table => new 157 | { 158 | Id = table.Column(nullable: false) 159 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 160 | CreatedBy = table.Column(nullable: false), 161 | IsActive = table.Column(nullable: false), 162 | CreatedTime = table.Column(nullable: false), 163 | UpdatedTime = table.Column(nullable: true), 164 | UpdatedBy = table.Column(nullable: true), 165 | PollId = table.Column(nullable: false), 166 | Name = table.Column(maxLength: 150, nullable: false), 167 | DisplayOrder = table.Column(nullable: false) 168 | }, 169 | constraints: table => 170 | { 171 | table.PrimaryKey("PK_PollAnswer", x => x.Id); 172 | table.ForeignKey( 173 | name: "FK_PollAnswer_Poll_PollId", 174 | column: x => x.PollId, 175 | principalTable: "Poll", 176 | principalColumn: "Id", 177 | onDelete: ReferentialAction.Cascade); 178 | }); 179 | 180 | migrationBuilder.CreateTable( 181 | name: "Article", 182 | columns: table => new 183 | { 184 | Id = table.Column(nullable: false) 185 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 186 | CreatedBy = table.Column(nullable: false), 187 | IsActive = table.Column(nullable: false), 188 | CreatedTime = table.Column(nullable: false), 189 | UpdatedTime = table.Column(nullable: true), 190 | UpdatedBy = table.Column(nullable: true), 191 | Title = table.Column(maxLength: 300, nullable: false), 192 | ShortDescription = table.Column(maxLength: 450, nullable: false), 193 | Description = table.Column(maxLength: 1500, nullable: false), 194 | ThumbnailImageId = table.Column(nullable: true), 195 | ReviewsCount = table.Column(nullable: false), 196 | RatingAverage = table.Column(nullable: false), 197 | IsPublished = table.Column(nullable: false), 198 | UserId = table.Column(nullable: true) 199 | }, 200 | constraints: table => 201 | { 202 | table.PrimaryKey("PK_Article", x => x.Id); 203 | table.ForeignKey( 204 | name: "FK_Article_Media_ThumbnailImageId", 205 | column: x => x.ThumbnailImageId, 206 | principalTable: "Media", 207 | principalColumn: "Id", 208 | onDelete: ReferentialAction.Restrict); 209 | table.ForeignKey( 210 | name: "FK_Article_User_UserId", 211 | column: x => x.UserId, 212 | principalTable: "User", 213 | principalColumn: "Id", 214 | onDelete: ReferentialAction.Restrict); 215 | }); 216 | 217 | migrationBuilder.CreateTable( 218 | name: "Contact", 219 | columns: table => new 220 | { 221 | Id = table.Column(nullable: false) 222 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 223 | CreatedBy = table.Column(nullable: false), 224 | IsActive = table.Column(nullable: false), 225 | CreatedTime = table.Column(nullable: false), 226 | UpdatedTime = table.Column(nullable: true), 227 | UpdatedBy = table.Column(nullable: true), 228 | UserId = table.Column(nullable: true), 229 | FullName = table.Column(maxLength: 150, nullable: false), 230 | PhoneNumber = table.Column(maxLength: 50, nullable: false), 231 | EmailAddress = table.Column(maxLength: 150, nullable: false), 232 | Content = table.Column(maxLength: 1500, nullable: false) 233 | }, 234 | constraints: table => 235 | { 236 | table.PrimaryKey("PK_Contact", x => x.Id); 237 | table.ForeignKey( 238 | name: "FK_Contact_User_UserId", 239 | column: x => x.UserId, 240 | principalTable: "User", 241 | principalColumn: "Id", 242 | onDelete: ReferentialAction.Restrict); 243 | }); 244 | 245 | migrationBuilder.CreateTable( 246 | name: "CourseAction", 247 | columns: table => new 248 | { 249 | Id = table.Column(nullable: false) 250 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 251 | CreatedBy = table.Column(nullable: false), 252 | IsActive = table.Column(nullable: false), 253 | CreatedTime = table.Column(nullable: false), 254 | UpdatedTime = table.Column(nullable: true), 255 | UpdatedBy = table.Column(nullable: true), 256 | UserId = table.Column(nullable: false), 257 | CourseId = table.Column(nullable: false), 258 | CourseLessonId = table.Column(nullable: false), 259 | Finished = table.Column(nullable: false) 260 | }, 261 | constraints: table => 262 | { 263 | table.PrimaryKey("PK_CourseAction", x => x.Id); 264 | table.ForeignKey( 265 | name: "FK_CourseAction_Course_CourseId", 266 | column: x => x.CourseId, 267 | principalTable: "Course", 268 | principalColumn: "Id", 269 | onDelete: ReferentialAction.Cascade); 270 | table.ForeignKey( 271 | name: "FK_CourseAction_CourseLesson_CourseLessonId", 272 | column: x => x.CourseLessonId, 273 | principalTable: "CourseLesson", 274 | principalColumn: "Id", 275 | onDelete: ReferentialAction.Cascade); 276 | table.ForeignKey( 277 | name: "FK_CourseAction_User_UserId", 278 | column: x => x.UserId, 279 | principalTable: "User", 280 | principalColumn: "Id", 281 | onDelete: ReferentialAction.Cascade); 282 | }); 283 | 284 | migrationBuilder.CreateTable( 285 | name: "PollVotingRecord", 286 | columns: table => new 287 | { 288 | Id = table.Column(nullable: false) 289 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 290 | CreatedBy = table.Column(nullable: false), 291 | IsActive = table.Column(nullable: false), 292 | CreatedTime = table.Column(nullable: false), 293 | UpdatedTime = table.Column(nullable: true), 294 | UpdatedBy = table.Column(nullable: true), 295 | PollAnswerId = table.Column(nullable: false), 296 | PollId = table.Column(nullable: false), 297 | UserId = table.Column(nullable: true) 298 | }, 299 | constraints: table => 300 | { 301 | table.PrimaryKey("PK_PollVotingRecord", x => x.Id); 302 | table.ForeignKey( 303 | name: "FK_PollVotingRecord_PollAnswer_PollAnswerId", 304 | column: x => x.PollAnswerId, 305 | principalTable: "PollAnswer", 306 | principalColumn: "Id", 307 | onDelete: ReferentialAction.Cascade); 308 | table.ForeignKey( 309 | name: "FK_PollVotingRecord_User_UserId", 310 | column: x => x.UserId, 311 | principalTable: "User", 312 | principalColumn: "Id", 313 | onDelete: ReferentialAction.Restrict); 314 | }); 315 | 316 | migrationBuilder.CreateTable( 317 | name: "ArticleCategory", 318 | columns: table => new 319 | { 320 | ArticleId = table.Column(nullable: false), 321 | CategoryId = table.Column(nullable: false) 322 | }, 323 | constraints: table => 324 | { 325 | table.PrimaryKey("PK_ArticleCategory", x => new { x.ArticleId, x.CategoryId }); 326 | table.ForeignKey( 327 | name: "FK_ArticleCategory_Article_ArticleId", 328 | column: x => x.ArticleId, 329 | principalTable: "Article", 330 | principalColumn: "Id", 331 | onDelete: ReferentialAction.Cascade); 332 | table.ForeignKey( 333 | name: "FK_ArticleCategory_Category_CategoryId", 334 | column: x => x.CategoryId, 335 | principalTable: "Category", 336 | principalColumn: "Id", 337 | onDelete: ReferentialAction.Cascade); 338 | }); 339 | 340 | migrationBuilder.CreateTable( 341 | name: "ArticleMedia", 342 | columns: table => new 343 | { 344 | ArticleId = table.Column(nullable: false), 345 | MediaId = table.Column(nullable: false) 346 | }, 347 | constraints: table => 348 | { 349 | table.PrimaryKey("PK_ArticleMedia", x => new { x.ArticleId, x.MediaId }); 350 | table.ForeignKey( 351 | name: "FK_ArticleMedia_Article_ArticleId", 352 | column: x => x.ArticleId, 353 | principalTable: "Article", 354 | principalColumn: "Id", 355 | onDelete: ReferentialAction.Cascade); 356 | table.ForeignKey( 357 | name: "FK_ArticleMedia_Media_MediaId", 358 | column: x => x.MediaId, 359 | principalTable: "Media", 360 | principalColumn: "Id", 361 | onDelete: ReferentialAction.Cascade); 362 | }); 363 | 364 | migrationBuilder.CreateTable( 365 | name: "Comment", 366 | columns: table => new 367 | { 368 | Id = table.Column(nullable: false) 369 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 370 | CreatedBy = table.Column(nullable: false), 371 | IsActive = table.Column(nullable: false), 372 | CreatedTime = table.Column(nullable: false), 373 | UpdatedTime = table.Column(nullable: true), 374 | UpdatedBy = table.Column(nullable: true), 375 | UserId = table.Column(nullable: true), 376 | ArticleId = table.Column(nullable: false), 377 | Status = table.Column(nullable: false), 378 | CommentText = table.Column(maxLength: 1500, nullable: false), 379 | CommenterName = table.Column(maxLength: 150, nullable: false), 380 | CommenterEmail = table.Column(maxLength: 150, nullable: false), 381 | ParentId = table.Column(nullable: true) 382 | }, 383 | constraints: table => 384 | { 385 | table.PrimaryKey("PK_Comment", x => x.Id); 386 | table.ForeignKey( 387 | name: "FK_Comment_Article_ArticleId", 388 | column: x => x.ArticleId, 389 | principalTable: "Article", 390 | principalColumn: "Id", 391 | onDelete: ReferentialAction.Cascade); 392 | table.ForeignKey( 393 | name: "FK_Comment_Comment_ParentId", 394 | column: x => x.ParentId, 395 | principalTable: "Comment", 396 | principalColumn: "Id", 397 | onDelete: ReferentialAction.Restrict); 398 | table.ForeignKey( 399 | name: "FK_Comment_User_UserId", 400 | column: x => x.UserId, 401 | principalTable: "User", 402 | principalColumn: "Id", 403 | onDelete: ReferentialAction.Restrict); 404 | }); 405 | 406 | migrationBuilder.CreateIndex( 407 | name: "IX_Article_ThumbnailImageId", 408 | table: "Article", 409 | column: "ThumbnailImageId"); 410 | 411 | migrationBuilder.CreateIndex( 412 | name: "IX_Article_UserId", 413 | table: "Article", 414 | column: "UserId"); 415 | 416 | migrationBuilder.CreateIndex( 417 | name: "IX_ArticleCategory_CategoryId", 418 | table: "ArticleCategory", 419 | column: "CategoryId"); 420 | 421 | migrationBuilder.CreateIndex( 422 | name: "IX_ArticleMedia_MediaId", 423 | table: "ArticleMedia", 424 | column: "MediaId"); 425 | 426 | migrationBuilder.CreateIndex( 427 | name: "IX_Category_Name", 428 | table: "Category", 429 | column: "Name", 430 | unique: true); 431 | 432 | migrationBuilder.CreateIndex( 433 | name: "IX_Category_ParentId", 434 | table: "Category", 435 | column: "ParentId"); 436 | 437 | migrationBuilder.CreateIndex( 438 | name: "IX_Comment_ArticleId", 439 | table: "Comment", 440 | column: "ArticleId"); 441 | 442 | migrationBuilder.CreateIndex( 443 | name: "IX_Comment_ParentId", 444 | table: "Comment", 445 | column: "ParentId"); 446 | 447 | migrationBuilder.CreateIndex( 448 | name: "IX_Comment_UserId", 449 | table: "Comment", 450 | column: "UserId"); 451 | 452 | migrationBuilder.CreateIndex( 453 | name: "IX_Contact_UserId", 454 | table: "Contact", 455 | column: "UserId"); 456 | 457 | migrationBuilder.CreateIndex( 458 | name: "IX_CourseAction_CourseId", 459 | table: "CourseAction", 460 | column: "CourseId"); 461 | 462 | migrationBuilder.CreateIndex( 463 | name: "IX_CourseAction_CourseLessonId", 464 | table: "CourseAction", 465 | column: "CourseLessonId"); 466 | 467 | migrationBuilder.CreateIndex( 468 | name: "IX_CourseAction_UserId", 469 | table: "CourseAction", 470 | column: "UserId"); 471 | 472 | migrationBuilder.CreateIndex( 473 | name: "IX_CourseLesson_CourseId", 474 | table: "CourseLesson", 475 | column: "CourseId"); 476 | 477 | migrationBuilder.CreateIndex( 478 | name: "IX_PollAnswer_PollId", 479 | table: "PollAnswer", 480 | column: "PollId"); 481 | 482 | migrationBuilder.CreateIndex( 483 | name: "IX_PollVotingRecord_PollAnswerId", 484 | table: "PollVotingRecord", 485 | column: "PollAnswerId"); 486 | 487 | migrationBuilder.CreateIndex( 488 | name: "IX_PollVotingRecord_UserId", 489 | table: "PollVotingRecord", 490 | column: "UserId"); 491 | 492 | migrationBuilder.CreateIndex( 493 | name: "IX_User_Email", 494 | table: "User", 495 | column: "Email", 496 | unique: true); 497 | } 498 | 499 | protected override void Down(MigrationBuilder migrationBuilder) 500 | { 501 | migrationBuilder.DropTable( 502 | name: "ArticleCategory"); 503 | 504 | migrationBuilder.DropTable( 505 | name: "ArticleMedia"); 506 | 507 | migrationBuilder.DropTable( 508 | name: "Comment"); 509 | 510 | migrationBuilder.DropTable( 511 | name: "Contact"); 512 | 513 | migrationBuilder.DropTable( 514 | name: "CourseAction"); 515 | 516 | migrationBuilder.DropTable( 517 | name: "PollVotingRecord"); 518 | 519 | migrationBuilder.DropTable( 520 | name: "Category"); 521 | 522 | migrationBuilder.DropTable( 523 | name: "Article"); 524 | 525 | migrationBuilder.DropTable( 526 | name: "CourseLesson"); 527 | 528 | migrationBuilder.DropTable( 529 | name: "PollAnswer"); 530 | 531 | migrationBuilder.DropTable( 532 | name: "Media"); 533 | 534 | migrationBuilder.DropTable( 535 | name: "User"); 536 | 537 | migrationBuilder.DropTable( 538 | name: "Course"); 539 | 540 | migrationBuilder.DropTable( 541 | name: "Poll"); 542 | } 543 | } 544 | } 545 | -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Migrations/PortalDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 6 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 7 | using Portal.Infrastructure.Persistence; 8 | 9 | namespace Portal.Infrastructure.Migrations 10 | { 11 | [DbContext(typeof(PortalDbContext))] 12 | partial class PortalDbContextModelSnapshot : ModelSnapshot 13 | { 14 | protected override void BuildModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) 19 | .HasAnnotation("ProductVersion", "3.1.9") 20 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 21 | 22 | modelBuilder.Entity("Portal.Domain.Entities.Article", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasColumnType("integer") 27 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 28 | 29 | b.Property("CreatedBy") 30 | .HasColumnType("integer"); 31 | 32 | b.Property("CreatedTime") 33 | .HasColumnType("timestamp without time zone"); 34 | 35 | b.Property("Description") 36 | .IsRequired() 37 | .HasColumnType("character varying(1500)") 38 | .HasMaxLength(1500); 39 | 40 | b.Property("IsActive") 41 | .HasColumnType("smallint"); 42 | 43 | b.Property("IsPublished") 44 | .HasColumnType("boolean"); 45 | 46 | b.Property("RatingAverage") 47 | .HasColumnType("double precision"); 48 | 49 | b.Property("ReviewsCount") 50 | .HasColumnType("integer"); 51 | 52 | b.Property("ShortDescription") 53 | .IsRequired() 54 | .HasColumnType("character varying(450)") 55 | .HasMaxLength(450); 56 | 57 | b.Property("ThumbnailImageId") 58 | .HasColumnType("integer"); 59 | 60 | b.Property("Title") 61 | .IsRequired() 62 | .HasColumnType("character varying(300)") 63 | .HasMaxLength(300); 64 | 65 | b.Property("UpdatedBy") 66 | .HasColumnType("integer"); 67 | 68 | b.Property("UpdatedTime") 69 | .HasColumnType("timestamp without time zone"); 70 | 71 | b.Property("UserId") 72 | .HasColumnType("integer"); 73 | 74 | b.HasKey("Id"); 75 | 76 | b.HasIndex("ThumbnailImageId"); 77 | 78 | b.HasIndex("UserId"); 79 | 80 | b.ToTable("Article"); 81 | }); 82 | 83 | modelBuilder.Entity("Portal.Domain.Entities.ArticleCategory", b => 84 | { 85 | b.Property("ArticleId") 86 | .HasColumnType("integer"); 87 | 88 | b.Property("CategoryId") 89 | .HasColumnType("integer"); 90 | 91 | b.HasKey("ArticleId", "CategoryId"); 92 | 93 | b.HasIndex("CategoryId"); 94 | 95 | b.ToTable("ArticleCategory"); 96 | }); 97 | 98 | modelBuilder.Entity("Portal.Domain.Entities.ArticleMedia", b => 99 | { 100 | b.Property("ArticleId") 101 | .HasColumnType("integer"); 102 | 103 | b.Property("MediaId") 104 | .HasColumnType("integer"); 105 | 106 | b.HasKey("ArticleId", "MediaId"); 107 | 108 | b.HasIndex("MediaId"); 109 | 110 | b.ToTable("ArticleMedia"); 111 | }); 112 | 113 | modelBuilder.Entity("Portal.Domain.Entities.Category", b => 114 | { 115 | b.Property("Id") 116 | .ValueGeneratedOnAdd() 117 | .HasColumnType("integer") 118 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 119 | 120 | b.Property("CreatedBy") 121 | .HasColumnType("integer"); 122 | 123 | b.Property("CreatedTime") 124 | .HasColumnType("timestamp without time zone"); 125 | 126 | b.Property("Description") 127 | .IsRequired() 128 | .HasColumnType("character varying(1500)") 129 | .HasMaxLength(1500); 130 | 131 | b.Property("IsActive") 132 | .HasColumnType("smallint"); 133 | 134 | b.Property("MetaDescription") 135 | .IsRequired() 136 | .HasColumnType("character varying(255)") 137 | .HasMaxLength(255); 138 | 139 | b.Property("MetaKeywords") 140 | .IsRequired() 141 | .HasColumnType("character varying(255)") 142 | .HasMaxLength(255); 143 | 144 | b.Property("MetaTitle") 145 | .IsRequired() 146 | .HasColumnType("character varying(160)") 147 | .HasMaxLength(160); 148 | 149 | b.Property("Name") 150 | .IsRequired() 151 | .HasColumnType("character varying(150)") 152 | .HasMaxLength(150); 153 | 154 | b.Property("ParentId") 155 | .HasColumnType("integer"); 156 | 157 | b.Property("UpdatedBy") 158 | .HasColumnType("integer"); 159 | 160 | b.Property("UpdatedTime") 161 | .HasColumnType("timestamp without time zone"); 162 | 163 | b.HasKey("Id"); 164 | 165 | b.HasIndex("Name") 166 | .IsUnique(); 167 | 168 | b.HasIndex("ParentId"); 169 | 170 | b.ToTable("Category"); 171 | }); 172 | 173 | modelBuilder.Entity("Portal.Domain.Entities.Comment", b => 174 | { 175 | b.Property("Id") 176 | .ValueGeneratedOnAdd() 177 | .HasColumnType("integer") 178 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 179 | 180 | b.Property("ArticleId") 181 | .HasColumnType("integer"); 182 | 183 | b.Property("CommentText") 184 | .IsRequired() 185 | .HasColumnType("character varying(1500)") 186 | .HasMaxLength(1500); 187 | 188 | b.Property("CommenterEmail") 189 | .IsRequired() 190 | .HasColumnType("character varying(150)") 191 | .HasMaxLength(150); 192 | 193 | b.Property("CommenterName") 194 | .IsRequired() 195 | .HasColumnType("character varying(150)") 196 | .HasMaxLength(150); 197 | 198 | b.Property("CreatedBy") 199 | .HasColumnType("integer"); 200 | 201 | b.Property("CreatedTime") 202 | .HasColumnType("timestamp without time zone"); 203 | 204 | b.Property("IsActive") 205 | .HasColumnType("smallint"); 206 | 207 | b.Property("ParentId") 208 | .HasColumnType("integer"); 209 | 210 | b.Property("Status") 211 | .HasColumnType("integer"); 212 | 213 | b.Property("UpdatedBy") 214 | .HasColumnType("integer"); 215 | 216 | b.Property("UpdatedTime") 217 | .HasColumnType("timestamp without time zone"); 218 | 219 | b.Property("UserId") 220 | .HasColumnType("integer"); 221 | 222 | b.HasKey("Id"); 223 | 224 | b.HasIndex("ArticleId"); 225 | 226 | b.HasIndex("ParentId"); 227 | 228 | b.HasIndex("UserId"); 229 | 230 | b.ToTable("Comment"); 231 | }); 232 | 233 | modelBuilder.Entity("Portal.Domain.Entities.Contact", b => 234 | { 235 | b.Property("Id") 236 | .ValueGeneratedOnAdd() 237 | .HasColumnType("integer") 238 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 239 | 240 | b.Property("Content") 241 | .IsRequired() 242 | .HasColumnType("character varying(1500)") 243 | .HasMaxLength(1500); 244 | 245 | b.Property("CreatedBy") 246 | .HasColumnType("integer"); 247 | 248 | b.Property("CreatedTime") 249 | .HasColumnType("timestamp without time zone"); 250 | 251 | b.Property("EmailAddress") 252 | .IsRequired() 253 | .HasColumnType("character varying(150)") 254 | .HasMaxLength(150); 255 | 256 | b.Property("FullName") 257 | .IsRequired() 258 | .HasColumnType("character varying(150)") 259 | .HasMaxLength(150); 260 | 261 | b.Property("IsActive") 262 | .HasColumnType("smallint"); 263 | 264 | b.Property("PhoneNumber") 265 | .IsRequired() 266 | .HasColumnType("character varying(50)") 267 | .HasMaxLength(50); 268 | 269 | b.Property("UpdatedBy") 270 | .HasColumnType("integer"); 271 | 272 | b.Property("UpdatedTime") 273 | .HasColumnType("timestamp without time zone"); 274 | 275 | b.Property("UserId") 276 | .HasColumnType("integer"); 277 | 278 | b.HasKey("Id"); 279 | 280 | b.HasIndex("UserId"); 281 | 282 | b.ToTable("Contact"); 283 | }); 284 | 285 | modelBuilder.Entity("Portal.Domain.Entities.Course", b => 286 | { 287 | b.Property("Id") 288 | .ValueGeneratedOnAdd() 289 | .HasColumnType("integer") 290 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 291 | 292 | b.Property("CreatedBy") 293 | .HasColumnType("integer"); 294 | 295 | b.Property("CreatedTime") 296 | .HasColumnType("timestamp without time zone"); 297 | 298 | b.Property("Description") 299 | .IsRequired() 300 | .HasColumnType("character varying(1500)") 301 | .HasMaxLength(1500); 302 | 303 | b.Property("IsActive") 304 | .HasColumnType("smallint"); 305 | 306 | b.Property("IsPublished") 307 | .HasColumnType("boolean"); 308 | 309 | b.Property("MetaDescription") 310 | .IsRequired() 311 | .HasColumnType("character varying(255)") 312 | .HasMaxLength(255); 313 | 314 | b.Property("MetaKeywords") 315 | .IsRequired() 316 | .HasColumnType("character varying(255)") 317 | .HasMaxLength(255); 318 | 319 | b.Property("MetaTitle") 320 | .IsRequired() 321 | .HasColumnType("character varying(160)") 322 | .HasMaxLength(160); 323 | 324 | b.Property("Name") 325 | .IsRequired() 326 | .HasColumnType("character varying(150)") 327 | .HasMaxLength(150); 328 | 329 | b.Property("ShortDescription") 330 | .IsRequired() 331 | .HasColumnType("character varying(450)") 332 | .HasMaxLength(450); 333 | 334 | b.Property("UpdatedBy") 335 | .HasColumnType("integer"); 336 | 337 | b.Property("UpdatedTime") 338 | .HasColumnType("timestamp without time zone"); 339 | 340 | b.HasKey("Id"); 341 | 342 | b.ToTable("Course"); 343 | }); 344 | 345 | modelBuilder.Entity("Portal.Domain.Entities.CourseAction", b => 346 | { 347 | b.Property("Id") 348 | .ValueGeneratedOnAdd() 349 | .HasColumnType("integer") 350 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 351 | 352 | b.Property("CourseId") 353 | .HasColumnType("integer"); 354 | 355 | b.Property("CourseLessonId") 356 | .HasColumnType("integer"); 357 | 358 | b.Property("CreatedBy") 359 | .HasColumnType("integer"); 360 | 361 | b.Property("CreatedTime") 362 | .HasColumnType("timestamp without time zone"); 363 | 364 | b.Property("Finished") 365 | .HasColumnType("boolean"); 366 | 367 | b.Property("IsActive") 368 | .HasColumnType("smallint"); 369 | 370 | b.Property("UpdatedBy") 371 | .HasColumnType("integer"); 372 | 373 | b.Property("UpdatedTime") 374 | .HasColumnType("timestamp without time zone"); 375 | 376 | b.Property("UserId") 377 | .HasColumnType("integer"); 378 | 379 | b.HasKey("Id"); 380 | 381 | b.HasIndex("CourseId"); 382 | 383 | b.HasIndex("CourseLessonId"); 384 | 385 | b.HasIndex("UserId"); 386 | 387 | b.ToTable("CourseAction"); 388 | }); 389 | 390 | modelBuilder.Entity("Portal.Domain.Entities.CourseLesson", b => 391 | { 392 | b.Property("Id") 393 | .ValueGeneratedOnAdd() 394 | .HasColumnType("integer") 395 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 396 | 397 | b.Property("CourseId") 398 | .HasColumnType("integer"); 399 | 400 | b.Property("CreatedBy") 401 | .HasColumnType("integer"); 402 | 403 | b.Property("CreatedTime") 404 | .HasColumnType("timestamp without time zone"); 405 | 406 | b.Property("Description") 407 | .IsRequired() 408 | .HasColumnType("character varying(1500)") 409 | .HasMaxLength(1500); 410 | 411 | b.Property("IsActive") 412 | .HasColumnType("smallint"); 413 | 414 | b.Property("Name") 415 | .IsRequired() 416 | .HasColumnType("character varying(150)") 417 | .HasMaxLength(150); 418 | 419 | b.Property("ShortDescription") 420 | .IsRequired() 421 | .HasColumnType("character varying(450)") 422 | .HasMaxLength(450); 423 | 424 | b.Property("UpdatedBy") 425 | .HasColumnType("integer"); 426 | 427 | b.Property("UpdatedTime") 428 | .HasColumnType("timestamp without time zone"); 429 | 430 | b.HasKey("Id"); 431 | 432 | b.HasIndex("CourseId"); 433 | 434 | b.ToTable("CourseLesson"); 435 | }); 436 | 437 | modelBuilder.Entity("Portal.Domain.Entities.Media", b => 438 | { 439 | b.Property("Id") 440 | .ValueGeneratedOnAdd() 441 | .HasColumnType("integer") 442 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 443 | 444 | b.Property("Caption") 445 | .IsRequired() 446 | .HasColumnType("character varying(150)") 447 | .HasMaxLength(150); 448 | 449 | b.Property("CreatedBy") 450 | .HasColumnType("integer"); 451 | 452 | b.Property("CreatedTime") 453 | .HasColumnType("timestamp without time zone"); 454 | 455 | b.Property("FileName") 456 | .IsRequired() 457 | .HasColumnType("character varying(150)") 458 | .HasMaxLength(150); 459 | 460 | b.Property("FileSize") 461 | .HasColumnType("integer"); 462 | 463 | b.Property("IsActive") 464 | .HasColumnType("smallint"); 465 | 466 | b.Property("MediaType") 467 | .HasColumnType("integer"); 468 | 469 | b.Property("UpdatedBy") 470 | .HasColumnType("integer"); 471 | 472 | b.Property("UpdatedTime") 473 | .HasColumnType("timestamp without time zone"); 474 | 475 | b.HasKey("Id"); 476 | 477 | b.ToTable("Media"); 478 | }); 479 | 480 | modelBuilder.Entity("Portal.Domain.Entities.Poll", b => 481 | { 482 | b.Property("Id") 483 | .ValueGeneratedOnAdd() 484 | .HasColumnType("integer") 485 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 486 | 487 | b.Property("AllowGuestsToVote") 488 | .HasColumnType("boolean"); 489 | 490 | b.Property("CreatedBy") 491 | .HasColumnType("integer"); 492 | 493 | b.Property("CreatedTime") 494 | .HasColumnType("timestamp without time zone"); 495 | 496 | b.Property("EndDate") 497 | .HasColumnType("timestamp without time zone"); 498 | 499 | b.Property("IsActive") 500 | .HasColumnType("smallint"); 501 | 502 | b.Property("Name") 503 | .IsRequired() 504 | .HasColumnType("character varying(150)") 505 | .HasMaxLength(150); 506 | 507 | b.Property("ShowOnHomePage") 508 | .HasColumnType("boolean"); 509 | 510 | b.Property("StartDate") 511 | .HasColumnType("timestamp without time zone"); 512 | 513 | b.Property("UpdatedBy") 514 | .HasColumnType("integer"); 515 | 516 | b.Property("UpdatedTime") 517 | .HasColumnType("timestamp without time zone"); 518 | 519 | b.HasKey("Id"); 520 | 521 | b.ToTable("Poll"); 522 | }); 523 | 524 | modelBuilder.Entity("Portal.Domain.Entities.PollAnswer", b => 525 | { 526 | b.Property("Id") 527 | .ValueGeneratedOnAdd() 528 | .HasColumnType("integer") 529 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 530 | 531 | b.Property("CreatedBy") 532 | .HasColumnType("integer"); 533 | 534 | b.Property("CreatedTime") 535 | .HasColumnType("timestamp without time zone"); 536 | 537 | b.Property("DisplayOrder") 538 | .HasColumnType("integer"); 539 | 540 | b.Property("IsActive") 541 | .HasColumnType("smallint"); 542 | 543 | b.Property("Name") 544 | .IsRequired() 545 | .HasColumnType("character varying(150)") 546 | .HasMaxLength(150); 547 | 548 | b.Property("PollId") 549 | .HasColumnType("integer"); 550 | 551 | b.Property("UpdatedBy") 552 | .HasColumnType("integer"); 553 | 554 | b.Property("UpdatedTime") 555 | .HasColumnType("timestamp without time zone"); 556 | 557 | b.HasKey("Id"); 558 | 559 | b.HasIndex("PollId"); 560 | 561 | b.ToTable("PollAnswer"); 562 | }); 563 | 564 | modelBuilder.Entity("Portal.Domain.Entities.PollVotingRecord", b => 565 | { 566 | b.Property("Id") 567 | .ValueGeneratedOnAdd() 568 | .HasColumnType("integer") 569 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 570 | 571 | b.Property("CreatedBy") 572 | .HasColumnType("integer"); 573 | 574 | b.Property("CreatedTime") 575 | .HasColumnType("timestamp without time zone"); 576 | 577 | b.Property("IsActive") 578 | .HasColumnType("smallint"); 579 | 580 | b.Property("PollAnswerId") 581 | .HasColumnType("integer"); 582 | 583 | b.Property("PollId") 584 | .HasColumnType("integer"); 585 | 586 | b.Property("UpdatedBy") 587 | .HasColumnType("integer"); 588 | 589 | b.Property("UpdatedTime") 590 | .HasColumnType("timestamp without time zone"); 591 | 592 | b.Property("UserId") 593 | .HasColumnType("integer"); 594 | 595 | b.HasKey("Id"); 596 | 597 | b.HasIndex("PollAnswerId"); 598 | 599 | b.HasIndex("UserId"); 600 | 601 | b.ToTable("PollVotingRecord"); 602 | }); 603 | 604 | modelBuilder.Entity("Portal.Domain.Entities.User", b => 605 | { 606 | b.Property("Id") 607 | .ValueGeneratedOnAdd() 608 | .HasColumnType("integer") 609 | .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); 610 | 611 | b.Property("CreatedBy") 612 | .HasColumnType("integer"); 613 | 614 | b.Property("CreatedTime") 615 | .HasColumnType("timestamp without time zone"); 616 | 617 | b.Property("Email") 618 | .IsRequired() 619 | .HasColumnType("character varying(150)") 620 | .HasMaxLength(150); 621 | 622 | b.Property("FullName") 623 | .IsRequired() 624 | .HasColumnType("character varying(150)") 625 | .HasMaxLength(150); 626 | 627 | b.Property("IsActive") 628 | .HasColumnType("smallint"); 629 | 630 | b.Property("IsDeleted") 631 | .HasColumnType("boolean"); 632 | 633 | b.Property("UpdatedBy") 634 | .HasColumnType("integer"); 635 | 636 | b.Property("UpdatedTime") 637 | .HasColumnType("timestamp without time zone"); 638 | 639 | b.HasKey("Id"); 640 | 641 | b.HasIndex("Email") 642 | .IsUnique(); 643 | 644 | b.ToTable("User"); 645 | }); 646 | 647 | modelBuilder.Entity("Portal.Domain.Entities.Article", b => 648 | { 649 | b.HasOne("Portal.Domain.Entities.Media", "ThumbnailImage") 650 | .WithMany() 651 | .HasForeignKey("ThumbnailImageId"); 652 | 653 | b.HasOne("Portal.Domain.Entities.User", null) 654 | .WithMany("Articles") 655 | .HasForeignKey("UserId"); 656 | }); 657 | 658 | modelBuilder.Entity("Portal.Domain.Entities.ArticleCategory", b => 659 | { 660 | b.HasOne("Portal.Domain.Entities.Article", "Article") 661 | .WithMany("ArticleCategories") 662 | .HasForeignKey("ArticleId") 663 | .OnDelete(DeleteBehavior.Cascade) 664 | .IsRequired(); 665 | 666 | b.HasOne("Portal.Domain.Entities.Category", "Category") 667 | .WithMany("ArticleCategories") 668 | .HasForeignKey("CategoryId") 669 | .OnDelete(DeleteBehavior.Cascade) 670 | .IsRequired(); 671 | }); 672 | 673 | modelBuilder.Entity("Portal.Domain.Entities.ArticleMedia", b => 674 | { 675 | b.HasOne("Portal.Domain.Entities.Article", "Article") 676 | .WithMany("ArticleMedias") 677 | .HasForeignKey("ArticleId") 678 | .OnDelete(DeleteBehavior.Cascade) 679 | .IsRequired(); 680 | 681 | b.HasOne("Portal.Domain.Entities.Media", "Media") 682 | .WithMany("ArticleMedias") 683 | .HasForeignKey("MediaId") 684 | .OnDelete(DeleteBehavior.Cascade) 685 | .IsRequired(); 686 | }); 687 | 688 | modelBuilder.Entity("Portal.Domain.Entities.Category", b => 689 | { 690 | b.HasOne("Portal.Domain.Entities.Category", "Parent") 691 | .WithMany() 692 | .HasForeignKey("ParentId"); 693 | }); 694 | 695 | modelBuilder.Entity("Portal.Domain.Entities.Comment", b => 696 | { 697 | b.HasOne("Portal.Domain.Entities.Article", "Article") 698 | .WithMany("Comments") 699 | .HasForeignKey("ArticleId") 700 | .OnDelete(DeleteBehavior.Cascade) 701 | .IsRequired(); 702 | 703 | b.HasOne("Portal.Domain.Entities.Comment", "Parent") 704 | .WithMany("Replies") 705 | .HasForeignKey("ParentId"); 706 | 707 | b.HasOne("Portal.Domain.Entities.User", "User") 708 | .WithMany("Comments") 709 | .HasForeignKey("UserId"); 710 | }); 711 | 712 | modelBuilder.Entity("Portal.Domain.Entities.Contact", b => 713 | { 714 | b.HasOne("Portal.Domain.Entities.User", "User") 715 | .WithMany("Contacts") 716 | .HasForeignKey("UserId"); 717 | }); 718 | 719 | modelBuilder.Entity("Portal.Domain.Entities.CourseAction", b => 720 | { 721 | b.HasOne("Portal.Domain.Entities.Course", "Course") 722 | .WithMany("CourseActions") 723 | .HasForeignKey("CourseId") 724 | .OnDelete(DeleteBehavior.Cascade) 725 | .IsRequired(); 726 | 727 | b.HasOne("Portal.Domain.Entities.CourseLesson", "CourseLesson") 728 | .WithMany("CourseActions") 729 | .HasForeignKey("CourseLessonId") 730 | .OnDelete(DeleteBehavior.Cascade) 731 | .IsRequired(); 732 | 733 | b.HasOne("Portal.Domain.Entities.User", "User") 734 | .WithMany("CourseActions") 735 | .HasForeignKey("UserId") 736 | .OnDelete(DeleteBehavior.Cascade) 737 | .IsRequired(); 738 | }); 739 | 740 | modelBuilder.Entity("Portal.Domain.Entities.CourseLesson", b => 741 | { 742 | b.HasOne("Portal.Domain.Entities.Course", "Course") 743 | .WithMany("CourseLessons") 744 | .HasForeignKey("CourseId") 745 | .OnDelete(DeleteBehavior.Cascade) 746 | .IsRequired(); 747 | }); 748 | 749 | modelBuilder.Entity("Portal.Domain.Entities.PollAnswer", b => 750 | { 751 | b.HasOne("Portal.Domain.Entities.Poll", "Poll") 752 | .WithMany("PollAnswers") 753 | .HasForeignKey("PollId") 754 | .OnDelete(DeleteBehavior.Cascade) 755 | .IsRequired(); 756 | }); 757 | 758 | modelBuilder.Entity("Portal.Domain.Entities.PollVotingRecord", b => 759 | { 760 | b.HasOne("Portal.Domain.Entities.PollAnswer", "PollAnswer") 761 | .WithMany("PollVotingRecords") 762 | .HasForeignKey("PollAnswerId") 763 | .OnDelete(DeleteBehavior.Cascade) 764 | .IsRequired(); 765 | 766 | b.HasOne("Portal.Domain.Entities.User", "User") 767 | .WithMany("PollVotingRecords") 768 | .HasForeignKey("UserId"); 769 | }); 770 | #pragma warning restore 612, 618 771 | } 772 | } 773 | } 774 | -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Articles/ArticleConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Articles 7 | { 8 | public class ArticleConfiguration : IEntityTypeConfiguration
9 | { 10 | public void Configure(EntityTypeBuilder
builder) 11 | { 12 | builder.Property(s => s.Title).IsRequired().HasMaxLength((int)MaxLengthSize.Title); 13 | builder.Property(s => s.ShortDescription).IsRequired().HasMaxLength((int)MaxLengthSize.ShortDescription); 14 | builder.Property(s => s.Description).IsRequired().HasMaxLength((int)MaxLengthSize.Description); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Categories/CategoryConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Categories 7 | { 8 | public class CategoryConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.Name).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | builder.Property(s => s.Description).IsRequired().HasMaxLength((int)MaxLengthSize.Description); 14 | builder.Property(s => s.MetaTitle).IsRequired().HasMaxLength((int)MaxLengthSize.MetaTitle); 15 | builder.Property(s => s.MetaKeywords).IsRequired().HasMaxLength((int)MaxLengthSize.MetaDescription); 16 | builder.Property(s => s.MetaDescription).IsRequired().HasMaxLength((int)MaxLengthSize.MetaDescription); 17 | builder.HasIndex(s => s.Name).IsUnique(); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Comments/CommentConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Comments 7 | { 8 | public class CommentConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.ArticleId).IsRequired(); 13 | builder.Property(s => s.CommentText).IsRequired().HasMaxLength((int)MaxLengthSize.Description); 14 | builder.Property(s => s.CommenterName).IsRequired().HasMaxLength((int)MaxLengthSize.EmailAddress); 15 | builder.Property(s => s.CommenterEmail).IsRequired().HasMaxLength((int)MaxLengthSize.EmailAddress); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Contacts/ContactConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Contacts 7 | { 8 | public class ContactConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.FullName).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | builder.Property(s => s.EmailAddress).IsRequired().HasMaxLength((int)MaxLengthSize.EmailAddress); 14 | builder.Property(s => s.PhoneNumber).IsRequired().HasMaxLength((int)MaxLengthSize.PhoneNumber); 15 | builder.Property(s => s.Content).IsRequired().HasMaxLength((int)MaxLengthSize.Description); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Courses/CourseActionConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Entities; 4 | 5 | namespace Portal.Infrastructure.Persistence.Configurations.Courses 6 | { 7 | public class CourseActionConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder.Property(s => s.UserId).IsRequired(); 12 | builder.Property(s => s.CourseId).IsRequired(); 13 | builder.Property(s => s.CourseLessonId).IsRequired(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Courses/CourseConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Courses 7 | { 8 | public class CourseConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.Name).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | builder.Property(s => s.Description).IsRequired().HasMaxLength((int)MaxLengthSize.Description); 14 | builder.Property(s => s.ShortDescription).IsRequired().HasMaxLength((int)MaxLengthSize.ShortDescription); 15 | builder.Property(s => s.MetaTitle).IsRequired().HasMaxLength((int)MaxLengthSize.MetaTitle); 16 | builder.Property(s => s.MetaDescription).IsRequired().HasMaxLength((int)MaxLengthSize.MetaDescription); 17 | builder.Property(s => s.MetaKeywords).IsRequired().HasMaxLength((int)MaxLengthSize.MetaDescription); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Courses/CourseLessonConfiguratio.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Courses 7 | { 8 | public class CourseLessonConfiguratio : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.Name).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | builder.Property(s => s.Description).IsRequired().HasMaxLength((int)MaxLengthSize.Description); 14 | builder.Property(s => s.ShortDescription).IsRequired().HasMaxLength((int)MaxLengthSize.ShortDescription); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Medias/MediaConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Medias 7 | { 8 | public class MediaConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.FileName).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | builder.Property(s => s.Caption).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 14 | builder.Property(s => s.MediaType).IsRequired(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Polls/PollAnswerConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Polls 7 | { 8 | public class PollAnswerConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.Name).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | builder.Property(s => s.PollId).IsRequired(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Polls/PollConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Polls 7 | { 8 | public class PollConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.Name).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Polls/PollVotingRecordConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Entities; 4 | 5 | namespace Portal.Infrastructure.Persistence.Configurations.Polls 6 | { 7 | public class PollVotingRecordConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder.Property(s => s.PollId).IsRequired(); 12 | builder.Property(s => s.PollAnswerId).IsRequired(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/Configurations/Users/UserConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Portal.Domain.Common; 4 | using Portal.Domain.Entities; 5 | 6 | namespace Portal.Infrastructure.Persistence.Configurations.Users 7 | { 8 | public class UserConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | builder.Property(s => s.FullName).IsRequired().HasMaxLength((int)MaxLengthSize.Name); 13 | builder.Property(s => s.Email).IsRequired().HasMaxLength((int)MaxLengthSize.EmailAddress); 14 | builder.HasIndex(s => s.Email).IsUnique(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/EntityFramework/EfRepository.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Portal.Domain.Common; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | 8 | namespace Portal.Infrastructure.Persistence.EntityFramework 9 | { 10 | public class EfRepository : IRepository where T : BaseEntity 11 | { 12 | private readonly DbContext _context; 13 | private DbSet _entities; 14 | 15 | public EfRepository(DbContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | protected virtual DbSet Entities => _entities ?? _context.Set(); 21 | 22 | public IQueryable GetAll => Entities; 23 | 24 | public IQueryable GetAllNoTracking => Entities.AsNoTracking(); 25 | 26 | public bool Any(Expression> expression) 27 | { 28 | return Entities.Any(expression); 29 | } 30 | 31 | public int Commit() 32 | { 33 | try 34 | { 35 | return _context.SaveChanges(); 36 | } 37 | catch (DbUpdateException exception) 38 | { 39 | GetFullErrorTextAndRollbackEntityChanges(exception); 40 | return -1; 41 | } 42 | } 43 | 44 | public int Delete(T entity) 45 | { 46 | if (entity == null) 47 | throw new ArgumentNullException(nameof(entity)); 48 | 49 | Entities.Remove(entity); 50 | return Commit(); 51 | } 52 | 53 | public int DeleteBulk(IEnumerable entities) 54 | { 55 | if (entities == null) 56 | throw new ArgumentNullException(nameof(entities)); 57 | 58 | Entities.RemoveRange(entities); 59 | return Commit(); 60 | } 61 | 62 | public T Get(Expression> expression, params Expression>[] includes) 63 | { 64 | var query = Entities.Where(expression); 65 | return includes.Aggregate(query, (current, includeProperty) => current.Include(includeProperty)).FirstOrDefault(); 66 | } 67 | 68 | public T GetById(int Id) 69 | { 70 | return Entities.Find(Id); 71 | } 72 | 73 | public IQueryable GetMany(Expression> expression, params Expression>[] includes) 74 | { 75 | var query = Entities.Where(expression); 76 | return includes.Aggregate(query, (current, includeProperty) => current.Include(includeProperty)); 77 | } 78 | 79 | public int InsertBulk(IEnumerable entities) 80 | { 81 | if (entities == null) 82 | throw new ArgumentNullException(nameof(entities)); 83 | 84 | Entities.AddRange(entities); 85 | return Commit(); 86 | } 87 | 88 | public T InsertWithoutCommit(T entity) 89 | { 90 | if (entity == null) 91 | throw new ArgumentNullException(nameof(entity)); 92 | 93 | Entities.Add(entity); 94 | return entity; 95 | } 96 | 97 | public int Remove(T entity) 98 | { 99 | if (entity == null) 100 | throw new ArgumentNullException(nameof(entity)); 101 | try 102 | { 103 | Entities.Remove(entity); 104 | return 1; 105 | } 106 | catch 107 | { 108 | return -1; 109 | } 110 | } 111 | 112 | public int Update(T entity) 113 | { 114 | if (entity == null) 115 | throw new ArgumentNullException(nameof(entity)); 116 | 117 | Entities.Update(entity); 118 | return Commit(); 119 | } 120 | 121 | public int UpdateWithoutCommit(T entity) 122 | { 123 | if (entity == null) 124 | throw new ArgumentNullException(nameof(entity)); 125 | 126 | try 127 | { 128 | Entities.Update(entity); 129 | return 1; 130 | } 131 | catch 132 | { 133 | return -1; 134 | } 135 | } 136 | 137 | protected string GetFullErrorTextAndRollbackEntityChanges(DbUpdateException exception) 138 | { 139 | if (_context is DbContext dbContext) 140 | { 141 | var entries = dbContext.ChangeTracker.Entries() 142 | .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified).ToList(); 143 | 144 | entries.ForEach(entry => 145 | { 146 | try 147 | { 148 | entry.State = EntityState.Unchanged; 149 | } 150 | catch (InvalidOperationException) 151 | { 152 | } 153 | }); 154 | } 155 | 156 | try 157 | { 158 | _context.SaveChanges(); 159 | return exception.ToString(); 160 | } 161 | catch (Exception ex) 162 | { 163 | return ex.ToString(); 164 | } 165 | } 166 | } 167 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/IRepository.cs: -------------------------------------------------------------------------------- 1 | using Portal.Domain.Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | 7 | namespace Portal.Infrastructure.Persistence 8 | { 9 | public interface IRepository where T : BaseEntity 10 | { 11 | T GetById(int Id); 12 | 13 | IQueryable GetAll { get; } 14 | 15 | IQueryable GetAllNoTracking { get; } 16 | 17 | T Get(Expression> expression, params Expression>[] includes); 18 | 19 | IQueryable GetMany(Expression> expression, params Expression>[] includes); 20 | 21 | T InsertWithoutCommit(T entity); 22 | 23 | int InsertBulk(IEnumerable entities); 24 | 25 | int Update(T entity); 26 | 27 | int UpdateWithoutCommit(T entity); 28 | 29 | int Delete(T entity); 30 | 31 | int Remove(T entity); 32 | 33 | int Commit(); 34 | 35 | int DeleteBulk(IEnumerable entities); 36 | 37 | bool Any(Expression> expression); 38 | } 39 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Persistence/PortalDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Portal.Domain.Entities; 3 | 4 | namespace Portal.Infrastructure.Persistence 5 | { 6 | public class PortalDbContext : DbContext 7 | { 8 | public PortalDbContext(DbContextOptions options) : base(options) 9 | { 10 | } 11 | 12 | protected override void OnModelCreating(ModelBuilder modelBuilder) 13 | { 14 | modelBuilder.Entity() 15 | .HasKey(f => new { f.ArticleId, f.CategoryId }); 16 | 17 | modelBuilder.Entity() 18 | .HasOne(b => b.Article) 19 | .WithMany(b => b.ArticleCategories) 20 | .HasForeignKey(f => f.ArticleId); 21 | 22 | modelBuilder.Entity() 23 | .HasOne(b => b.Category) 24 | .WithMany(b => b.ArticleCategories) 25 | .HasForeignKey(f => f.CategoryId); 26 | 27 | modelBuilder.Entity() 28 | .HasKey(f => new { f.ArticleId, f.MediaId }); 29 | 30 | modelBuilder.Entity() 31 | .HasOne(b => b.Article) 32 | .WithMany(b => b.ArticleMedias) 33 | .HasForeignKey(f => f.ArticleId); 34 | 35 | modelBuilder.Entity() 36 | .HasOne(b => b.Media) 37 | .WithMany(b => b.ArticleMedias) 38 | .HasForeignKey(f => f.MediaId); 39 | 40 | modelBuilder.ApplyConfigurationsFromAssembly(typeof(PortalDbContext).Assembly); 41 | base.OnModelCreating(modelBuilder); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Libraries/Portal.Infrastructure/Portal.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | all 11 | runtime; build; native; contentfiles; analyzers; buildtransitive 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Libraries/Portal.Shared/Portal.Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Libraries/Portal.Shared/Result/Result.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Portal.Shared.Result 7 | { 8 | public class Result 9 | { 10 | public bool Success { get; set; } 11 | 12 | public string Message { get; set; } 13 | 14 | public Result(bool success, string message) 15 | { 16 | Success = success; 17 | Message = message; 18 | } 19 | 20 | public static Result Ok(IQueryable value, string message) 21 | { 22 | return new Result(value, true, message); 23 | } 24 | 25 | public static ResultSingle Ok(T value, string message) 26 | { 27 | return new ResultSingle(value, true, message); 28 | } 29 | 30 | public static Result Fail(string message) 31 | { 32 | return new Result(null, false, message); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Libraries/Portal.Shared/Result/ResultSingle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Portal.Shared.Result 6 | { 7 | public class ResultSingle : Result 8 | { 9 | public T Value { get; set; } 10 | 11 | public ResultSingle(T value, bool success, string message) : base(success, message) 12 | { 13 | Value = value; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Libraries/Portal.Shared/Result/Result{T}.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Portal.Shared.Result 7 | { 8 | public class Result : Result 9 | { 10 | public IQueryable Value { get; set; } 11 | 12 | public Result(IQueryable value, bool success, string message) 13 | : base(success, message) 14 | { 15 | Value = value; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Portal-API.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30611.23 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{7F3D1024-0B37-4DBF-A80B-D70B76AC940B}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{35D1DD7B-FBDB-4CD7-976B-E0238D2B957D}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{FF0CF90B-6BD0-4529-BE4D-36AE8799BB5F}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Portal.Domain", "Libraries\Portal.Domain\Portal.Domain.csproj", "{92BB6094-200F-4162-B650-D31EA67602B1}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Portal.Infrastructure", "Libraries\Portal.Infrastructure\Portal.Infrastructure.csproj", "{5009864F-7D1F-41F1-9833-0956623ACBA9}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Portal.Application", "Libraries\Portal.Application\Portal.Application.csproj", "{920B6050-FD9B-4F49-A0E2-0EDF562E9A33}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Portal.API", "Presentation\Portal.API\Portal.API.csproj", "{46AD77DC-6DEC-4F9A-9F45-7B084151B790}" 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Portal.Shared", "Libraries\Portal.Shared\Portal.Shared.csproj", "{63324FDC-5D60-42D9-99BB-73B7B21D60BC}" 21 | EndProject 22 | Global 23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 24 | Debug|Any CPU = Debug|Any CPU 25 | Release|Any CPU = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {92BB6094-200F-4162-B650-D31EA67602B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {92BB6094-200F-4162-B650-D31EA67602B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {92BB6094-200F-4162-B650-D31EA67602B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {92BB6094-200F-4162-B650-D31EA67602B1}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {5009864F-7D1F-41F1-9833-0956623ACBA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {5009864F-7D1F-41F1-9833-0956623ACBA9}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {5009864F-7D1F-41F1-9833-0956623ACBA9}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {5009864F-7D1F-41F1-9833-0956623ACBA9}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {920B6050-FD9B-4F49-A0E2-0EDF562E9A33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {920B6050-FD9B-4F49-A0E2-0EDF562E9A33}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {920B6050-FD9B-4F49-A0E2-0EDF562E9A33}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {920B6050-FD9B-4F49-A0E2-0EDF562E9A33}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {46AD77DC-6DEC-4F9A-9F45-7B084151B790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {46AD77DC-6DEC-4F9A-9F45-7B084151B790}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {46AD77DC-6DEC-4F9A-9F45-7B084151B790}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {46AD77DC-6DEC-4F9A-9F45-7B084151B790}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {63324FDC-5D60-42D9-99BB-73B7B21D60BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {63324FDC-5D60-42D9-99BB-73B7B21D60BC}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {63324FDC-5D60-42D9-99BB-73B7B21D60BC}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {63324FDC-5D60-42D9-99BB-73B7B21D60BC}.Release|Any CPU.Build.0 = Release|Any CPU 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(NestedProjects) = preSolution 53 | {92BB6094-200F-4162-B650-D31EA67602B1} = {7F3D1024-0B37-4DBF-A80B-D70B76AC940B} 54 | {5009864F-7D1F-41F1-9833-0956623ACBA9} = {7F3D1024-0B37-4DBF-A80B-D70B76AC940B} 55 | {920B6050-FD9B-4F49-A0E2-0EDF562E9A33} = {7F3D1024-0B37-4DBF-A80B-D70B76AC940B} 56 | {46AD77DC-6DEC-4F9A-9F45-7B084151B790} = {35D1DD7B-FBDB-4CD7-976B-E0238D2B957D} 57 | {63324FDC-5D60-42D9-99BB-73B7B21D60BC} = {7F3D1024-0B37-4DBF-A80B-D70B76AC940B} 58 | EndGlobalSection 59 | GlobalSection(ExtensibilityGlobals) = postSolution 60 | SolutionGuid = {F60880BE-2AEE-4C3B-8368-ED2EB1BAC5C0} 61 | EndGlobalSection 62 | EndGlobal 63 | -------------------------------------------------------------------------------- /Presentation/Portal.API/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Portal.API.Controllers 4 | { 5 | public class HomeController : ControllerBase 6 | { 7 | [HttpGet("Test")] 8 | public IActionResult Index() 9 | { 10 | return Ok("Swagger testi içindir."); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Presentation/Portal.API/Portal.API.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | all 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Presentation/Portal.API/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Portal.API 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Presentation/Portal.API/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:64296", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "weatherforecast", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "Portal.API": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "weatherforecast", 24 | "applicationUrl": "http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Presentation/Portal.API/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using FluentValidation.AspNetCore; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Hosting; 12 | using Microsoft.Extensions.Logging; 13 | using Portal.Application.System; 14 | 15 | namespace Portal.API 16 | { 17 | public class Startup 18 | { 19 | public Startup(IConfiguration configuration) 20 | { 21 | Configuration = configuration; 22 | } 23 | 24 | public IConfiguration Configuration { get; } 25 | 26 | // This method gets called by the runtime. Use this method to add services to the container. 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | services.InjectApplicationServices(); 30 | services.AddCustomizedDataStore(Configuration); 31 | services.IntegrateSwagger(Configuration); 32 | services.AddApplication(); 33 | services.AddControllers() 34 | .AddFluentValidation(m => m.RegisterValidatorsFromAssemblyContaining()); 35 | } 36 | 37 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 38 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 39 | { 40 | if (env.IsDevelopment()) 41 | { 42 | app.UseDeveloperExceptionPage(); 43 | } 44 | app.UseRouting(); 45 | 46 | app.UseAuthorization(); 47 | app.ConfigSwagger(); 48 | app.UseEndpoints(endpoints => 49 | { 50 | endpoints.MapControllers(); 51 | }); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Presentation/Portal.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=localhost;Port=5432;Database=Portal;User Id=postgres;Password=1;Integrated Security=true;Pooling=true;" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*", 13 | "Swagger": { 14 | "Title": "Portal API", 15 | "Version": 1, 16 | "Description": "Youtube kanalinda yayinlanan projesinin doc" 17 | } 18 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Portal-API 2 | alidogankim youtube hesabımda yayınladığım eğitim serisi projesidir. 3 | --------------------------------------------------------------------------------