Made foreign keys required causing cascade deletion.

Removed completed TODO comments.
This commit is contained in:
Harrison Deng 2021-07-14 01:13:19 -05:00
parent 7e8a398741
commit bad22090a3
9 changed files with 109 additions and 193 deletions

View File

@ -1,14 +1,16 @@
using Props.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using IdentityServer4.EntityFramework.Options;
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.Extensions.Options;
using Props.Models;
using Props.Shared.Models;
using Props.Shop.Framework;
namespace Props.Data
{
@ -20,30 +22,42 @@ namespace Props.Data
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder) {
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ResultsPreferences>()
.Property(e => e.Order)
.HasConversion(
v => JsonSerializer.Serialize(v, null),
v => JsonSerializer.Deserialize<List<ResultsPreferences.Category>>(v, null),
v => JsonSerializer.Serialize(v, null),
v => JsonSerializer.Deserialize<List<ResultsPreferences.Category>>(v, null),
new ValueComparer<IList<ResultsPreferences.Category>>(
(a, b) => a.SequenceEqual(b),
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
c => (IList<ResultsPreferences.Category>) c.ToList()
c => (IList<ResultsPreferences.Category>)c.ToList()
)
);
modelBuilder.Entity<SearchOutline>()
.Property(e => e.ShopStates)
.HasConversion(
v => JsonSerializer.Serialize(v, null),
v => JsonSerializer.Serialize(v, null),
v => JsonSerializer.Deserialize<SearchOutline.ShopToggler>(v, null),
new ValueComparer<SearchOutline.ShopToggler>(
(a, b) => a.Equals(b),
c => c.GetHashCode(),
c => c.Clone()
c => c.Copy()
)
);
modelBuilder.Entity<SearchOutline>()
.Property(e => e.Filters)
.HasConversion(
v => JsonSerializer.Serialize(v, null),
v => JsonSerializer.Deserialize<Filters>(v, null),
new ValueComparer<Filters>(
(a, b) => a.Equals(b),
c => c.GetHashCode(),
c => c.Copy()
)
);
}

View File

@ -9,7 +9,7 @@ using Props.Data;
namespace Props.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20210712080053_InitialCreate")]
[Migration("20210714061021_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -324,6 +324,7 @@ namespace Props.Data.Migrations
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Order")
@ -345,54 +346,19 @@ namespace Props.Data.Migrations
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Currency")
.HasColumnType("INTEGER");
b.Property<bool>("EnableMaxShippingFee")
.HasColumnType("INTEGER");
b.Property<bool>("EnableUpperPrice")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnknownPurchaseCount")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnknownRatingCount")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnknownShipping")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnrated")
.HasColumnType("INTEGER");
b.Property<int>("LowerPrice")
.HasColumnType("INTEGER");
b.Property<string>("Filters")
.HasColumnType("TEXT");
b.Property<int>("MaxResults")
.HasColumnType("INTEGER");
b.Property<int>("MaxShippingFee")
.HasColumnType("INTEGER");
b.Property<int>("MinPurchases")
.HasColumnType("INTEGER");
b.Property<float>("MinRating")
.HasColumnType("REAL");
b.Property<int>("MinReviews")
.HasColumnType("INTEGER");
b.Property<string>("ShopStates")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("UpperPrice")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ApplicationUserId")
@ -408,6 +374,7 @@ namespace Props.Data.Migrations
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("CacheCommonSearches")
@ -482,21 +449,27 @@ namespace Props.Data.Migrations
{
b.HasOne("Props.Models.ApplicationUser", null)
.WithOne("ResultsPreferences")
.HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId");
.HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Models.SearchOutline", b =>
{
b.HasOne("Props.Models.ApplicationUser", null)
.WithOne("SearchOutline")
.HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId");
.HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Shared.Models.ApplicationPreferences", b =>
{
b.HasOne("Props.Models.ApplicationUser", null)
.WithOne("ApplicationPreferences")
.HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId");
.HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Models.ApplicationUser", b =>

View File

@ -112,7 +112,7 @@ namespace Props.Data.Migrations
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: true),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: false),
DarkMode = table.Column<bool>(type: "INTEGER", nullable: false),
CacheCommonSearches = table.Column<bool>(type: "INTEGER", nullable: false),
EnableSearchHistory = table.Column<bool>(type: "INTEGER", nullable: false)
@ -125,7 +125,7 @@ namespace Props.Data.Migrations
column: x => x.ApplicationUserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
@ -219,7 +219,7 @@ namespace Props.Data.Migrations
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: true),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: false),
Order = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
@ -230,7 +230,7 @@ namespace Props.Data.Migrations
column: x => x.ApplicationUserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
@ -239,21 +239,9 @@ namespace Props.Data.Migrations
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: true),
Currency = table.Column<int>(type: "INTEGER", nullable: false),
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: false),
Filters = table.Column<string>(type: "TEXT", nullable: true),
MaxResults = table.Column<int>(type: "INTEGER", nullable: false),
MinRating = table.Column<float>(type: "REAL", nullable: false),
KeepUnrated = table.Column<bool>(type: "INTEGER", nullable: false),
EnableUpperPrice = table.Column<bool>(type: "INTEGER", nullable: false),
UpperPrice = table.Column<int>(type: "INTEGER", nullable: false),
LowerPrice = table.Column<int>(type: "INTEGER", nullable: false),
MinPurchases = table.Column<int>(type: "INTEGER", nullable: false),
KeepUnknownPurchaseCount = table.Column<bool>(type: "INTEGER", nullable: false),
MinReviews = table.Column<int>(type: "INTEGER", nullable: false),
KeepUnknownRatingCount = table.Column<bool>(type: "INTEGER", nullable: false),
EnableMaxShippingFee = table.Column<bool>(type: "INTEGER", nullable: false),
MaxShippingFee = table.Column<int>(type: "INTEGER", nullable: false),
KeepUnknownShipping = table.Column<bool>(type: "INTEGER", nullable: false),
ShopStates = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
@ -264,7 +252,7 @@ namespace Props.Data.Migrations
column: x => x.ApplicationUserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(

View File

@ -322,6 +322,7 @@ namespace Props.Data.Migrations
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Order")
@ -343,54 +344,19 @@ namespace Props.Data.Migrations
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Currency")
.HasColumnType("INTEGER");
b.Property<bool>("EnableMaxShippingFee")
.HasColumnType("INTEGER");
b.Property<bool>("EnableUpperPrice")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnknownPurchaseCount")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnknownRatingCount")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnknownShipping")
.HasColumnType("INTEGER");
b.Property<bool>("KeepUnrated")
.HasColumnType("INTEGER");
b.Property<int>("LowerPrice")
.HasColumnType("INTEGER");
b.Property<string>("Filters")
.HasColumnType("TEXT");
b.Property<int>("MaxResults")
.HasColumnType("INTEGER");
b.Property<int>("MaxShippingFee")
.HasColumnType("INTEGER");
b.Property<int>("MinPurchases")
.HasColumnType("INTEGER");
b.Property<float>("MinRating")
.HasColumnType("REAL");
b.Property<int>("MinReviews")
.HasColumnType("INTEGER");
b.Property<string>("ShopStates")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("UpperPrice")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ApplicationUserId")
@ -406,6 +372,7 @@ namespace Props.Data.Migrations
.HasColumnType("INTEGER");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("CacheCommonSearches")
@ -480,21 +447,27 @@ namespace Props.Data.Migrations
{
b.HasOne("Props.Models.ApplicationUser", null)
.WithOne("ResultsPreferences")
.HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId");
.HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Models.SearchOutline", b =>
{
b.HasOne("Props.Models.ApplicationUser", null)
.WithOne("SearchOutline")
.HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId");
.HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Shared.Models.ApplicationPreferences", b =>
{
b.HasOne("Props.Models.ApplicationUser", null)
.WithOne("ApplicationPreferences")
.HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId");
.HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Props.Models.ApplicationUser", b =>

View File

@ -1,9 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace Props.Shared.Models
{
public class ApplicationPreferences
{
public int Id { get; set; }
[Required]
public string ApplicationUserId { get; set; }
public bool DarkMode { get; set; }

View File

@ -1,22 +1,36 @@
using Microsoft.AspNetCore.Identity;
using Props.Shared.Models;
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Props.Shared.Models;
namespace Props.Models
{
public class ApplicationUser : IdentityUser
{
[Required]
public virtual SearchOutline SearchOutline { get; private set; } = new SearchOutline();
public virtual SearchOutline SearchOutline { get; private set; }
[Required]
public virtual ResultsPreferences ResultsPreferences { get; private set; } = new ResultsPreferences();
public virtual ResultsPreferences ResultsPreferences { get; private set; }
[Required]
public virtual ApplicationPreferences ApplicationPreferences {get; private set; } = new ApplicationPreferences();
public virtual ApplicationPreferences ApplicationPreferences { get; private set; }
public ApplicationUser()
{
SearchOutline = new SearchOutline();
ResultsPreferences = new ResultsPreferences();
ApplicationPreferences = new ApplicationPreferences();
}
public ApplicationUser(SearchOutline searchOutline, ResultsPreferences resultsPreferences, ApplicationPreferences applicationPreferences)
{
this.SearchOutline = searchOutline;
this.ResultsPreferences = resultsPreferences;
this.ApplicationPreferences = applicationPreferences;
}
}
}

View File

@ -9,8 +9,9 @@ namespace Props.Models
public class ResultsPreferences
{
public int Id { get; set; }
[Required]
public string ApplicationUserId { get; set; }
[Required]
public IList<Category> Order { get; set; }

View File

@ -9,46 +9,11 @@ namespace Props.Models
public class SearchOutline
{
public int Id { get; set; }
[Required]
public string ApplicationUserId { get; set; }
public Currency Currency { get; set; } = Currency.CAD;
public Filters Filters { get; set; }
public int MaxResults { get; set; } = 100;
public float MinRating { get; set; } = 0.8f;
public bool KeepUnrated { get; set; } = true;
public bool EnableUpperPrice { get; set; } = false;
private int _upperPrice;
public int UpperPrice
{
get
{
return _upperPrice;
}
set
{
if (EnableUpperPrice) _upperPrice = value;
}
}
public int LowerPrice { get; set; }
public int MinPurchases { get; set; }
public bool KeepUnknownPurchaseCount { get; set; } = true;
public int MinReviews { get; set; }
public bool KeepUnknownRatingCount { get; set; } = true;
public bool EnableMaxShippingFee { get; set; }
private int _maxShippingFee;
public int MaxShippingFee
{
get
{
return _maxShippingFee;
}
set
{
if (EnableMaxShippingFee) _maxShippingFee = value;
}
}
public bool KeepUnknownShipping { get; set; } = true;
[Required]
public ShopToggler ShopStates { get; set; } = new ShopToggler();
@ -56,11 +21,14 @@ namespace Props.Models
public sealed class ShopToggler : HashSet<string>
{
public int TotalShops { get; set; }
public bool this[string name] {
get {
public bool this[string name]
{
get
{
return !this.Contains(name);
}
set {
set
{
if (value == false && TotalShops - Count <= 1) return;
if (value)
{
@ -73,10 +41,11 @@ namespace Props.Models
}
}
public ShopToggler Clone() {
ShopToggler clone = new ShopToggler();
clone.Union(this);
return clone;
public ShopToggler Copy()
{
ShopToggler copy = new ShopToggler();
copy.Union(this);
return copy;
}
public bool IsShopToggleable(string shop)
@ -91,35 +60,17 @@ namespace Props.Models
{
return false;
}
SearchOutline other = (SearchOutline) obj;
return
Id == other.Id &&
Currency == other.Currency &&
MaxResults == other.MaxResults &&
MinRating == other.MinRating &&
KeepUnrated == other.KeepUnrated &&
EnableUpperPrice == other.EnableUpperPrice &&
UpperPrice == other.UpperPrice &&
LowerPrice == other.LowerPrice &&
MinPurchases == other.MinPurchases &&
KeepUnknownPurchaseCount == other.KeepUnknownPurchaseCount &&
MinReviews == other.MinReviews &&
KeepUnknownRatingCount == other.KeepUnknownRatingCount &&
EnableMaxShippingFee == other.EnableMaxShippingFee &&
MaxShippingFee == other.MaxShippingFee &&
KeepUnknownShipping == other.KeepUnknownShipping &&
SearchOutline other = (SearchOutline)obj;
return
Id == other.Id &&
MaxResults == other.MaxResults &&
Filters.Equals(other.Filters) &&
ShopStates.Equals(other.ShopStates);
}
public override int GetHashCode()
{
return Id;
}
public SearchOutline DeepCopy() {
SearchOutline profile = (SearchOutline)MemberwiseClone();
profile.ShopStates = ShopStates.Clone();
return profile;
}
}
}

View File

@ -11,7 +11,6 @@ namespace Props
{
public class Program
{
// TODO: Rename project to Props
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();