/* “Commons Clause” License Condition v1.0 https://commonsclause.com/ The Software is provided to you by the Licensor under the License, as defined below, subject to the following condition. Without limiting other conditions in the License, the grant of rights under the License will not include, and the License does not grant to you, the right to Sell the Software. For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you under the License to provide to third parties, for a fee or other consideration (including without limitation fees for hosting or consulting/ support services related to the Software), a product or service whose value derives, entirely or substantially, from the functionality of the Software. Any license notice or attribution required by the License must also include this Commons Clause License Condition notice. Software: Open Archival License: GNU GPL: https://www.gnu.org/licenses/gpl-3.0.en.html Licensor: Vincent Allen */ using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using OpenArchival.DataAccess; using Microsoft.EntityFrameworkCore; using OpenArchival.DataAccess; namespace OpenArchival.DataAccess; public class ApplicationDbContext(DbContextOptions options) : IdentityDbContext(options) { public DbSet ArtifactGroupings { get; set; } public DbSet ArtifactEntries { get; set; } public DbSet ArtifactEntryTags { get; set; } public DbSet ArchiveCategories { get; set; } public DbSet ArtifactAssociatedNames { get; set; } public DbSet ArtifactFilePaths { get; set; } public DbSet ArtifactDefects { get; set; } public DbSet ArtifactStorageLocations { get; set; } public DbSet ArtifactTypes { get; set; } public DbSet ArtifactGroupingViewCounts { get; set; } public DbSet BlogPosts { get; set; } public DbSet BlogPostTags { get; set; } public DbSet BlogPostViews { get; set; } /// /// Configuration for what featured artifacts will be show on the homepage of the search page /// public DbSet SearchPageSliderEntries { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity() .HasMany(a => a.RelatedTo) .WithMany(a => a.RelatedBy) .UsingEntity(j => j.ToTable("ArtifactRelationships")); modelBuilder.Entity() .HasOne(a => a.StorageLocation) .WithMany(l => l.ArtifactEntries); modelBuilder.Entity() .HasOne(vc => vc.Grouping) .WithOne(g => g.ViewCount) .HasForeignKey(vc => vc.ArtifactGroupingId); modelBuilder.Entity() .OwnsOne(p => p.IdentifierFields) .ToJson(); modelBuilder.Entity() .HasMany(grouping => grouping.ChildArtifactEntries) .WithOne(entry => entry.ArtifactGrouping) .HasForeignKey(entry => entry.ArtifactGroupingId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity() .HasMany(entry => entry.Files) .WithOne(file => file.ParentArtifactEntry) .HasForeignKey(file => file.ParentArtifactEntryId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity() .HasOne(p => p.MainPhoto) .WithOne(p => p.ParentBlogPost) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity() .Navigation(g => g.IdentifierFields) .UsePropertyAccessMode(PropertyAccessMode.Field); var dictionaryComparer = new ValueComparer>( (dictionary1, dictionary2) => dictionary1.OrderBy(pair => pair.Key) .SequenceEqual(dictionary2.OrderBy(pair => pair.Key)), dictionary => dictionary.Aggregate( 0, (aggregatedHash, pair) => HashCode.Combine(aggregatedHash, pair.Key.GetHashCode(), pair.Value.GetHashCode())), sourceDictionary => new Dictionary(sourceDictionary) ); modelBuilder.Entity() .HasOne(post => post.MainPhoto) .WithOne(file => file.ParentBlogPost) .HasForeignKey(file => file.ParentBlogPostId); // Create the search vector columns for artifat groupings modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.AllSearchVector, "english", p => p.AllSearchString ) .HasIndex(p => p.AllSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.TagsSearchVector, "english", p => p.TagsSearchString ) .HasIndex(p => p.TagsSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.DefectsSearchVector, "english", p => p.DefectsSearchString ) .HasIndex(p => p.DefectsSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.ListedNamesSearchVector, "english", p => p.ListedNamesSearchString ) .HasIndex(p => p.ListedNamesSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.TitleSearchVector, "english", p => p.TitleSearchString ) .HasIndex(p => p.TitleSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.DescriptionSearchVector, "english", p => p.DescriptionSearchString ) .HasIndex(p => p.DescriptionSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.FilenamesSearchVector, "english", p => p.FilenamesSearchString ) .HasIndex(p => p.FilenamesSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.FileContentSearchVector, "english", p => p.FileContentSearchString ) .HasIndex(p => p.FileContentSearchVector) .HasMethod("GIN"); // Create the search vector columns for blog posts modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.ContentSearchVector, "english", p => p.Content) .HasIndex(p => p.ContentSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.TitleSearchVector, "english", p => p.Title) .HasIndex(p => p.TitleSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.TagsSearchVector, "english", p => p.TagsSearchString) .HasIndex(p => p.TagsSearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasGeneratedTsVectorColumn( p => p.AllSearchVector, "english", p => p.AllSearchString) .HasIndex(p => p.AllSearchVector) .HasMethod("GIN"); } }