Compare commits
No commits in common. "main" and "9ddaf31f2887a8aff64c8a08390a7fe5e2fa6697" have entirely different histories.
main
...
9ddaf31f28
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 1,
|
|
||||||
"isRoot": true,
|
|
||||||
"tools": {
|
|
||||||
"dotnet-ef": {
|
|
||||||
"version": "10.0.7",
|
|
||||||
"commands": [
|
|
||||||
"dotnet-ef"
|
|
||||||
],
|
|
||||||
"rollForward": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
###############################################################################
|
||||||
|
# Set default behavior to automatically normalize line endings.
|
||||||
|
###############################################################################
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set default behavior for command prompt diff.
|
||||||
|
#
|
||||||
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
|
# default for csharp files.
|
||||||
|
# Note: This is only used by command line
|
||||||
|
###############################################################################
|
||||||
|
#*.cs diff=csharp
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set the merge driver for project and solution files
|
||||||
|
#
|
||||||
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
|
# these files as binary and thus will always conflict and require user
|
||||||
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
|
###############################################################################
|
||||||
|
#*.sln merge=binary
|
||||||
|
#*.csproj merge=binary
|
||||||
|
#*.vbproj merge=binary
|
||||||
|
#*.vcxproj merge=binary
|
||||||
|
#*.vcproj merge=binary
|
||||||
|
#*.dbproj merge=binary
|
||||||
|
#*.fsproj merge=binary
|
||||||
|
#*.lsproj merge=binary
|
||||||
|
#*.wixproj merge=binary
|
||||||
|
#*.modelproj merge=binary
|
||||||
|
#*.sqlproj merge=binary
|
||||||
|
#*.wwaproj merge=binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# behavior for image files
|
||||||
|
#
|
||||||
|
# image files are treated as binary by default.
|
||||||
|
###############################################################################
|
||||||
|
#*.jpg binary
|
||||||
|
#*.png binary
|
||||||
|
#*.gif binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# diff behavior for common document formats
|
||||||
|
#
|
||||||
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
|
# entries below.
|
||||||
|
###############################################################################
|
||||||
|
#*.doc diff=astextplain
|
||||||
|
#*.DOC diff=astextplain
|
||||||
|
#*.docx diff=astextplain
|
||||||
|
#*.DOCX diff=astextplain
|
||||||
|
#*.dot diff=astextplain
|
||||||
|
#*.DOT diff=astextplain
|
||||||
|
#*.pdf diff=astextplain
|
||||||
|
#*.PDF diff=astextplain
|
||||||
|
#*.rtf diff=astextplain
|
||||||
|
#*.RTF diff=astextplain
|
||||||
397
.gitignore
vendored
397
.gitignore
vendored
@ -1,36 +1,363 @@
|
|||||||
################################################################################
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
|
## files generated by popular Visual Studio add-ons.
|
||||||
################################################################################
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
/FileShare-PC/bin
|
# User-specific files
|
||||||
/FileShare-PC/.vs
|
*.rsuser
|
||||||
/FileShare-PC/obj
|
*.suo
|
||||||
/FileShare-API/bin
|
*.user
|
||||||
/FileShare-API/obj
|
*.userosscache
|
||||||
/FileShare-Services/bin
|
*.sln.docstates
|
||||||
/FileShare-Services/obj
|
|
||||||
/FileShare-Web-VUE/.vscode
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
/FileShare-Web-VUE/obj
|
*.userprefs
|
||||||
/FileShare-Web-VUE/node_modules
|
|
||||||
/FileShare-Web-VUE/dist
|
# Mono auto generated files
|
||||||
/FileShare-Web-VUE/.vscode
|
mono_crash.*
|
||||||
/FileShare-EFCore/bin
|
|
||||||
/FileShare-EFCore/obj
|
# Build results
|
||||||
/FileShare-Common/bin
|
[Dd]ebug/
|
||||||
/FileShare-Common/obj
|
[Dd]ebugPublic/
|
||||||
/FileShare-API/logs
|
[Rr]elease/
|
||||||
/FileShare-API/fileshare-api.db
|
[Rr]eleases/
|
||||||
/FileShare-API/fileshare-api.db-shm
|
x64/
|
||||||
/FileShare-API/fileshare-api.db-wal
|
x86/
|
||||||
/FileShare-API/app.db
|
[Ww][Ii][Nn]32/
|
||||||
/FileShare-API/app.db-shm
|
[Aa][Rr][Mm]/
|
||||||
/FileShare-API/app.db-wal
|
[Aa][Rr][Mm]64/
|
||||||
/FileShare-API/wwwroot
|
bld/
|
||||||
/package-output
|
[Bb]in/
|
||||||
/package-scripts/tools
|
[Oo]bj/
|
||||||
/.vs
|
[Oo]ut/
|
||||||
/bin
|
[Ll]og/
|
||||||
/obj
|
[Ll]ogs/
|
||||||
/.claude
|
|
||||||
/.codex-build
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
/FileShare-API/Properties
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"chat.tools.terminal.autoApprove": {
|
|
||||||
"ForEach-Object": true,
|
|
||||||
"dotnet list": true,
|
|
||||||
"dotnet build": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
# Codex Rules
|
|
||||||
|
|
||||||
- Do not manually edit files under `FileShare-EFCore/Migrations/**`. These files are generated by EF scripts.
|
|
||||||
- When database schema changes are needed, update the EF model/configuration only and ask the user to generate migrations with the project scripts.
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<Application xmlns="https://github.com/avaloniaui"
|
<Application xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
x:Class="FileShare_PC.App"
|
x:Class="Avalonia_PC.App"
|
||||||
xmlns:local="using:FileShare_PC"
|
xmlns:local="using:Avalonia_PC"
|
||||||
RequestedThemeVariant="Default">
|
RequestedThemeVariant="Default">
|
||||||
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
||||||
|
|
||||||
@ -1,11 +1,11 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using FileShare_PC.ViewModels;
|
using Avalonia_PC.ViewModels;
|
||||||
using FileShare_PC.Views;
|
using Avalonia_PC.Views;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace FileShare_PC
|
namespace Avalonia_PC
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Avalonia 应用程序入口类,负责初始化 XAML 资源和设置主窗口。
|
/// Avalonia 应用程序入口类,负责初始化 XAML 资源和设置主窗口。
|
||||||
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
@ -1,9 +1,9 @@
|
|||||||
using FileShare_Services.Services.AuthService;
|
using Avalonia_Services.Services.AuthService;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FileShare_PC.Authentication
|
namespace Avalonia_PC.Authentication
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 第三方授权客户端占位实现。接入真实第三方接口时替换此服务即可。
|
/// 第三方授权客户端占位实现。接入真实第三方接口时替换此服务即可。
|
||||||
@ -1,11 +1,12 @@
|
|||||||
using Authentication;
|
using Authentication;
|
||||||
using FileShare_Common.Core;
|
using Avalonia_Common.Core;
|
||||||
using FileShare_Services.Core;
|
using Avalonia_Services.Core;
|
||||||
using FileShare_Services.Services.AuthService;
|
using Avalonia_Services.Services.AuthService;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FileShare_PC.Authentication
|
namespace Avalonia_PC.Authentication
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PC 端鉴权端点服务,实现 <see cref="IPcAuthEndpointService"/>,
|
/// PC 端鉴权端点服务,实现 <see cref="IPcAuthEndpointService"/>,
|
||||||
@ -13,10 +14,16 @@ namespace FileShare_PC.Authentication
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class PcAuthEndpointService(PcGlobalTokenService tokenService) : IPcAuthEndpointService
|
public sealed class PcAuthEndpointService(PcGlobalTokenService tokenService) : IPcAuthEndpointService
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||||
public async Task<IApiResponse> AuthorizeAsync(PcAuthorizeRequest request, ServiceEndpointContext ctx)
|
|
||||||
{
|
{
|
||||||
var token = await tokenService.AuthorizeAsync(request.AuthorizationCode);
|
PropertyNameCaseInsensitive = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<object?> AuthorizeAsync(ServiceEndpointContext ctx)
|
||||||
|
{
|
||||||
|
var request = Deserialize<PcAuthorizeRequest>(ctx.Body);
|
||||||
|
var token = await tokenService.AuthorizeAsync(request?.AuthorizationCode);
|
||||||
if (token is null)
|
if (token is null)
|
||||||
{
|
{
|
||||||
ctx.StatusCode = 401;
|
ctx.StatusCode = 401;
|
||||||
@ -27,9 +34,10 @@ namespace FileShare_PC.Authentication
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IApiResponse> RefreshAsync(PcRefreshRequest request, ServiceEndpointContext ctx)
|
public async Task<object?> RefreshAsync(ServiceEndpointContext ctx)
|
||||||
{
|
{
|
||||||
var token = request.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
var request = Deserialize<PcRefreshRequest>(ctx.Body);
|
||||||
|
var token = request?.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
||||||
var refreshed = await tokenService.RefreshAsync(token);
|
var refreshed = await tokenService.RefreshAsync(token);
|
||||||
if (refreshed is null)
|
if (refreshed is null)
|
||||||
{
|
{
|
||||||
@ -41,11 +49,25 @@ namespace FileShare_PC.Authentication
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<IApiResponse> LogoutAsync(PcLogoutRequest request, ServiceEndpointContext ctx)
|
public Task<object?> LogoutAsync(ServiceEndpointContext ctx)
|
||||||
{
|
{
|
||||||
var token = request.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
var request = Deserialize<PcLogoutRequest>(ctx.Body);
|
||||||
|
var token = request?.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
||||||
tokenService.Logout(token);
|
tokenService.Logout(token);
|
||||||
return Task.FromResult<IApiResponse>(ResponseHelper.Succeed("退出成功"));
|
return Task.FromResult<object?>(ResponseHelper.Succeed("退出成功"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将 JSON 请求体反序列化为指定类型。
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">目标类型。</typeparam>
|
||||||
|
/// <param name="body">JSON 请求体字符串,可为空。</param>
|
||||||
|
/// <returns>反序列化后的对象;若 body 为空则返回默认值。</returns>
|
||||||
|
private static T? Deserialize<T>(string? body)
|
||||||
|
{
|
||||||
|
return string.IsNullOrWhiteSpace(body)
|
||||||
|
? default
|
||||||
|
: JsonSerializer.Deserialize<T>(body, JsonOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1,10 +1,10 @@
|
|||||||
using Authentication;
|
using Authentication;
|
||||||
using FileShare_Services.Core;
|
using Avalonia_Services.Core;
|
||||||
using System;
|
using System;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FileShare_PC.Authentication
|
namespace Avalonia_PC.Authentication
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PC 端鉴权服务,基于全局 Token 验证用户身份,实现 <see cref="IAuthService"/>。
|
/// PC 端鉴权服务,基于全局 Token 验证用户身份,实现 <see cref="IAuthService"/>。
|
||||||
@ -1,4 +1,4 @@
|
|||||||
using FileShare_Services.Services.AuthService;
|
using Avalonia_Services.Services.AuthService;
|
||||||
using System;
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
@ -13,8 +13,6 @@
|
|||||||
<Content Include="www\**\*">
|
<Content Include="www\**\*">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="..\tools\ffmpeg\bin\ffmpeg.exe" Link="tools\ffmpeg\bin\ffmpeg.exe" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
|
||||||
<Content Include="..\tools\ffmpeg\bin\ffprobe.exe" Link="tools\ffmpeg\bin\ffprobe.exe" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -43,8 +41,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\FileShare-Services\FileShare-Services.csproj" />
|
<ProjectReference Include="..\Avalonia-Services\Avalonia-Services.csproj" />
|
||||||
<ProjectReference Include="..\FileShare-Common\FileShare-Common.csproj" />
|
<ProjectReference Include="..\Avalonia-Common\Avalonia-Common.csproj" />
|
||||||
<ProjectReference Include="..\FileShare-EFCore\FileShare-EFCore.csproj" />
|
<ProjectReference Include="..\Avalonia-EFCore\Avalonia-EFCore.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
11
Avalonia-PC.slnx
Normal file
11
Avalonia-PC.slnx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="../Avalonia-API/Avalonia-API.csproj" Id="e33aba9a-a56b-4f6b-8eaa-3acbed65ebad" />
|
||||||
|
<Project Path="../Avalonia-Common/Avalonia-Common.csproj" Id="caed4118-2161-4382-90b8-35fb4efe3b5f" />
|
||||||
|
<Project Path="../Avalonia-EFCore/Avalonia-EFCore.csproj" Id="64557501-62a7-4863-b2bf-1570b8c6fecb" />
|
||||||
|
<Project Path="../Avalonia-Services/Avalonia-Services.csproj" Id="b8757cf9-5422-4c67-acae-3c967c95f866" />
|
||||||
|
<Project Path="../Avalonia-Web-VUE/avalonia-web-vue.esproj">
|
||||||
|
<Build />
|
||||||
|
<Deploy />
|
||||||
|
</Project>
|
||||||
|
<Project Path="Avalonia-PC.csproj" />
|
||||||
|
</Solution>
|
||||||
@ -1,138 +0,0 @@
|
|||||||
using FileShare_Common.Core;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using FileShare_EFCore.Models;
|
|
||||||
using FileShare_Services.Core;
|
|
||||||
using FileShare_Services.Services.AuthService;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace FileShare_API.Authentication
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// API 鉴权端点服务,实现 <see cref="IApiAuthEndpointService"/>,
|
|
||||||
/// 处理登录、刷新 Token 和登出操作,使用 JWT 与 Refresh Token 机制。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ApiAuthEndpointService(
|
|
||||||
AppDataContext db,
|
|
||||||
JwtTokenService jwtTokenService,
|
|
||||||
RefreshTokenService refreshTokenService) : IApiAuthEndpointService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 处理用户登录请求。根据账号(邮箱或用户名)查找或创建用户,
|
|
||||||
/// 生成 JWT Access Token 和 Refresh Token 并返回。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ctx">服务端点上下文,包含请求体、请求头等信息。</param>
|
|
||||||
/// <returns>包含 AccessToken、RefreshToken 及过期时间的认证响应。</returns>
|
|
||||||
public async Task<IApiResponse> LoginAsync(ApiLoginRequest request, ServiceEndpointContext ctx)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(request.Account))
|
|
||||||
{
|
|
||||||
ctx.StatusCode = 400;
|
|
||||||
return ResponseHelper.Failure(400, "账号不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await db.Users.FirstOrDefaultAsync(
|
|
||||||
x => x.Email == request.Account || x.Name == request.Account);
|
|
||||||
|
|
||||||
if (user is null)
|
|
||||||
{
|
|
||||||
user = new UserEntity
|
|
||||||
{
|
|
||||||
Name = request.Account,
|
|
||||||
Email = request.Account.Contains('@') ? request.Account : null,
|
|
||||||
};
|
|
||||||
db.Users.Add(user);
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
var roles = NormalizeRoles(request.Roles);
|
|
||||||
var accessToken = jwtTokenService.CreateAccessToken(user, roles);
|
|
||||||
var refreshToken = await refreshTokenService.CreateAsync(
|
|
||||||
user.Id,
|
|
||||||
ctx.GetHeader("User-Agent"),
|
|
||||||
GetRemoteIpAddress(ctx));
|
|
||||||
|
|
||||||
return ResponseHelper.Ok(new AuthTokenResponse(
|
|
||||||
accessToken.Token,
|
|
||||||
refreshToken.Token,
|
|
||||||
accessToken.ExpiresAt,
|
|
||||||
refreshToken.Entity.ExpiresAt,
|
|
||||||
roles), "登录成功");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 使用 Refresh Token 轮换新的 Access Token 和 Refresh Token。
|
|
||||||
/// 旧的 Refresh Token 会被撤销并替换。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ctx">服务端点上下文,包含请求体中的 RefreshToken。</param>
|
|
||||||
/// <returns>新的 Token 对;若 Refresh Token 无效则返回 401 错误。</returns>
|
|
||||||
public async Task<IApiResponse> RefreshAsync(ApiRefreshTokenRequest request, ServiceEndpointContext ctx)
|
|
||||||
{
|
|
||||||
var rotated = await refreshTokenService.RotateAsync(
|
|
||||||
request.RefreshToken,
|
|
||||||
ctx.GetHeader("User-Agent"),
|
|
||||||
GetRemoteIpAddress(ctx));
|
|
||||||
|
|
||||||
if (rotated is null)
|
|
||||||
{
|
|
||||||
ctx.StatusCode = 401;
|
|
||||||
return ResponseHelper.Failure(401, "刷新 token 无效或已过期");
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await db.Users.FindAsync(rotated.Value.Entity.UserId);
|
|
||||||
if (user is null)
|
|
||||||
{
|
|
||||||
ctx.StatusCode = 401;
|
|
||||||
return ResponseHelper.Failure(401, "用户不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
var roles = new[] { "Admin" };
|
|
||||||
var accessToken = jwtTokenService.CreateAccessToken(user, roles);
|
|
||||||
|
|
||||||
return ResponseHelper.Ok(new AuthTokenResponse(
|
|
||||||
accessToken.Token,
|
|
||||||
rotated.Value.Token,
|
|
||||||
accessToken.ExpiresAt,
|
|
||||||
rotated.Value.Entity.ExpiresAt,
|
|
||||||
roles), "刷新成功");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 处理用户登出请求,撤销指定的 Refresh Token。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ctx">服务端点上下文,包含请求体中的 RefreshToken。</param>
|
|
||||||
/// <returns>登出成功的响应。</returns>
|
|
||||||
public async Task<IApiResponse> LogoutAsync(ApiLogoutRequest request, ServiceEndpointContext ctx)
|
|
||||||
{
|
|
||||||
await refreshTokenService.RevokeAsync(request.RefreshToken);
|
|
||||||
return ResponseHelper.Succeed("退出成功");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从上下文的 Items 中提取 ASP.NET Core HttpContext,并获取客户端远程 IP 地址。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ctx">服务端点上下文。</param>
|
|
||||||
/// <returns>客户端 IP 地址字符串;若无法获取则返回 null。</returns>
|
|
||||||
private static string? GetRemoteIpAddress(ServiceEndpointContext ctx)
|
|
||||||
{
|
|
||||||
return ctx.Items.TryGetValue("HttpContext", out var value) && value is HttpContext httpContext
|
|
||||||
? httpContext.Connection.RemoteIpAddress?.ToString()
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 规范化角色数组:去空白、去重(忽略大小写),为空时默认返回 Admin 角色。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="roles">原始角色数组,可为 null。</param>
|
|
||||||
/// <returns>规范化后的角色数组。</returns>
|
|
||||||
private static string[] NormalizeRoles(string[]? roles)
|
|
||||||
{
|
|
||||||
var normalized = roles?
|
|
||||||
.Where(role => !string.IsNullOrWhiteSpace(role))
|
|
||||||
.Select(role => role.Trim())
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
return normalized is { Length: > 0 } ? normalized : ["Admin"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
namespace FileShare_API.Authentication
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// JWT 鉴权配置选项,从 appsettings.json 的 Jwt 节绑定。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class JwtOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置 Token 签发者。
|
|
||||||
/// </summary>
|
|
||||||
public string Issuer { get; set; } = "FileShare-API";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置 Token 受众。
|
|
||||||
/// </summary>
|
|
||||||
public string Audience { get; set; } = "FileShare-Client";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置签名密钥(至少 32 字节)。
|
|
||||||
/// </summary>
|
|
||||||
public string SigningKey { get; set; } = "change-this-development-signing-key-at-least-32-bytes";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置 Access Token 有效期(分钟),默认 60 分钟。
|
|
||||||
/// </summary>
|
|
||||||
public int AccessTokenMinutes { get; set; } = 60;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置 Refresh Token 有效期(天),默认 30 天。
|
|
||||||
/// </summary>
|
|
||||||
public int RefreshTokenDays { get; set; } = 30;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
using FileShare_EFCore.Models;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FileShare_API.Authentication
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// JWT Token 服务,负责创建包含用户声明和角色的 Access Token。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class JwtTokenService(IOptions<JwtOptions> options)
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// JWT 配置选项。
|
|
||||||
/// </summary>
|
|
||||||
private readonly JwtOptions _options = options.Value;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建包含用户声明和角色的 JWT Access Token。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">用户实体。</param>
|
|
||||||
/// <param name="roles">角色集合。</param>
|
|
||||||
/// <returns>包含 Token 字符串和过期时间的元组。</returns>
|
|
||||||
public (string Token, DateTime ExpiresAt) CreateAccessToken(UserEntity user, IReadOnlyCollection<string> roles)
|
|
||||||
{
|
|
||||||
var expiresAt = DateTime.UtcNow.AddMinutes(_options.AccessTokenMinutes);
|
|
||||||
var claims = new List<Claim>
|
|
||||||
{
|
|
||||||
new(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
|
|
||||||
new(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
|
||||||
new(ClaimTypes.Name, user.Name ?? user.Email ?? $"user-{user.Id}"),
|
|
||||||
new("auth_type", "api-jwt"),
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var role in roles.Where(role => !string.IsNullOrWhiteSpace(role)).Distinct(StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
claims.Add(new Claim(ClaimTypes.Role, role));
|
|
||||||
}
|
|
||||||
|
|
||||||
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.SigningKey));
|
|
||||||
var credentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
|
|
||||||
var jwt = new JwtSecurityToken(
|
|
||||||
issuer: _options.Issuer,
|
|
||||||
audience: _options.Audience,
|
|
||||||
claims: claims,
|
|
||||||
notBefore: DateTime.UtcNow,
|
|
||||||
expires: expiresAt,
|
|
||||||
signingCredentials: credentials);
|
|
||||||
|
|
||||||
return (new JwtSecurityTokenHandler().WriteToken(jwt), expiresAt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
using FileShare_EFCore.Database;
|
|
||||||
using FileShare_EFCore.Models;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FileShare_API.Authentication
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Refresh Token 服务,负责创建、查找、撤销和轮换 Refresh Token,
|
|
||||||
/// Token 原文经 SHA256 哈希后存入数据库以保证安全性。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class RefreshTokenService(AppDataContext db, IOptions<JwtOptions> options)
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// JWT 配置选项。
|
|
||||||
/// </summary>
|
|
||||||
private readonly JwtOptions _options = options.Value;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建一个新的 Refresh Token,生成随机 Token 原文并存储其哈希到数据库。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId">关联的用户 ID。</param>
|
|
||||||
/// <param name="device">创建设备标识(如 User-Agent)。</param>
|
|
||||||
/// <param name="ipAddress">客户端 IP 地址。</param>
|
|
||||||
/// <param name="cancellationToken">取消令牌。</param>
|
|
||||||
/// <returns>包含 Token 原文和实体记录的元组。</returns>
|
|
||||||
public async Task<(string Token, ApiRefreshTokenEntity Entity)> CreateAsync(
|
|
||||||
int userId,
|
|
||||||
string? device,
|
|
||||||
string? ipAddress,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var token = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
|
|
||||||
var entity = new ApiRefreshTokenEntity
|
|
||||||
{
|
|
||||||
UserId = userId,
|
|
||||||
TokenHash = HashToken(token),
|
|
||||||
ExpiresAt = DateTime.UtcNow.AddDays(_options.RefreshTokenDays),
|
|
||||||
Device = device,
|
|
||||||
IpAddress = ipAddress,
|
|
||||||
};
|
|
||||||
|
|
||||||
db.ApiRefreshTokens.Add(entity);
|
|
||||||
await db.SaveChangesAsync(cancellationToken);
|
|
||||||
return (token, entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找有效的 Refresh Token 实体。Token 原文会被哈希后查询数据库,
|
|
||||||
/// 仅返回未过期且未被撤销的 Token。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="token">Refresh Token 原文。</param>
|
|
||||||
/// <param name="cancellationToken">取消令牌。</param>
|
|
||||||
/// <returns>有效的 Token 实体;若无效或不存在则返回 null。</returns>
|
|
||||||
public async Task<ApiRefreshTokenEntity?> FindActiveAsync(string? token, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(token))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hash = HashToken(token);
|
|
||||||
var entity = await db.ApiRefreshTokens.FirstOrDefaultAsync(x => x.TokenHash == hash, cancellationToken);
|
|
||||||
return entity?.IsActive == true ? entity : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 撤销指定的 Refresh Token,将其 RevokedAt 设为当前时间。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="token">要撤销的 Refresh Token 原文。</param>
|
|
||||||
/// <param name="cancellationToken">取消令牌。</param>
|
|
||||||
public async Task RevokeAsync(string? token, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var entity = await FindActiveAsync(token, cancellationToken);
|
|
||||||
if (entity is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.RevokedAt = DateTime.UtcNow;
|
|
||||||
await db.SaveChangesAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 轮换 Refresh Token:撤销旧的并创建新的,将新 Token 的哈希关联到旧记录。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="token">旧的 Refresh Token 原文。</param>
|
|
||||||
/// <param name="device">当前设备标识。</param>
|
|
||||||
/// <param name="ipAddress">当前客户端 IP 地址。</param>
|
|
||||||
/// <param name="cancellationToken">取消令牌。</param>
|
|
||||||
/// <returns>新的 Token 对;若旧 Token 无效则返回 null。</returns>
|
|
||||||
public async Task<(string Token, ApiRefreshTokenEntity Entity)?> RotateAsync(
|
|
||||||
string? token,
|
|
||||||
string? device,
|
|
||||||
string? ipAddress,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var current = await FindActiveAsync(token, cancellationToken);
|
|
||||||
if (current is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var next = await CreateAsync(current.UserId, device, ipAddress, cancellationToken);
|
|
||||||
current.RevokedAt = DateTime.UtcNow;
|
|
||||||
current.ReplacedByTokenHash = next.Entity.TokenHash;
|
|
||||||
await db.SaveChangesAsync(cancellationToken);
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 对 Token 原文进行 SHA256 哈希,返回十六进制字符串。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="token">Token 原文。</param>
|
|
||||||
/// <returns>SHA256 哈希后的十六进制字符串。</returns>
|
|
||||||
private static string HashToken(string token)
|
|
||||||
{
|
|
||||||
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(token));
|
|
||||||
return Convert.ToHexString(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
using FileShare_API.Authentication;
|
|
||||||
using FileShare_API.Services;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using FileShare_Services.Core;
|
|
||||||
using FileShare_Services.Endpoints;
|
|
||||||
using FileShare_Services.Services;
|
|
||||||
using FileShare_Services.Services.AuthService;
|
|
||||||
using FileShare_Services.Services.FileLibrary;
|
|
||||||
using FileShare_Services.Services.QrCode;
|
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FileShare_API.Configuration
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// API 项目服务配置扩展类,负责注册数据库、鉴权、业务服务和统一端点。
|
|
||||||
/// </summary>
|
|
||||||
public static class ServicesConfiguration
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 注册统一端点及其依赖的服务(含数据库)。
|
|
||||||
/// 所有业务端点定义在 FileShare-Services/Endpoints/AppEndpoints.cs。
|
|
||||||
/// </summary>
|
|
||||||
public static IServiceCollection AddUnifiedApiServices(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
// ---- 数据库 ----
|
|
||||||
// 从 appsettings.json 读取 DatabaseConfiguration 节
|
|
||||||
// 注册默认数据库提供程序(SQLite / MySQL / PostgreSQL / SqlServer)
|
|
||||||
DatabaseProviderRegistry.RegisterDefaults();
|
|
||||||
|
|
||||||
var databaseConfig = configuration
|
|
||||||
.GetSection(nameof(DatabaseConfiguration))
|
|
||||||
.Get<DatabaseConfiguration>()
|
|
||||||
?? DatabaseConfiguration.ForSQLite("app.db");
|
|
||||||
|
|
||||||
// 注册 AppDataContext(共享数据上下文)
|
|
||||||
services.AddAppDatabase<AppDataContext>(databaseConfig);
|
|
||||||
|
|
||||||
// ---- 业务服务 ----
|
|
||||||
services.AddScoped<WeatherForecastService>();
|
|
||||||
var thumbnailOptions = configuration
|
|
||||||
.GetSection(nameof(ThumbnailStorageOptions))
|
|
||||||
.Get<ThumbnailStorageOptions>()
|
|
||||||
?? new ThumbnailStorageOptions();
|
|
||||||
services.AddSingleton(thumbnailOptions);
|
|
||||||
services.AddSingleton<IVideoThumbnailService>(sp =>
|
|
||||||
new VideoThumbnailService(sp.GetRequiredService<ThumbnailStorageOptions>()));
|
|
||||||
services.AddScoped<IThumbnailStreamService, ThumbnailStreamService>();
|
|
||||||
services.AddScoped<IFileLibraryService, FileLibraryService>();
|
|
||||||
services.AddScoped<IFileLibraryEndpointService, FileLibraryEndpointService>();
|
|
||||||
services.AddScoped<IFileStreamService, FileStreamService>();
|
|
||||||
services.AddScoped<IQrCodeService, QrCodeService>();
|
|
||||||
services.Configure<FileLibraryScanOptions>(configuration.GetSection(nameof(FileLibraryScanOptions)));
|
|
||||||
services.AddHostedService<FileLibraryScanHostedService>();
|
|
||||||
services.AddDataProtection()
|
|
||||||
.PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "data-protection-keys")));
|
|
||||||
|
|
||||||
// ---- API 鉴权 ----
|
|
||||||
var jwtSection = configuration.GetSection("Jwt");
|
|
||||||
services.Configure<JwtOptions>(jwtSection);
|
|
||||||
var jwtOptions = jwtSection.Get<JwtOptions>() ?? new JwtOptions();
|
|
||||||
services
|
|
||||||
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
||||||
.AddJwtBearer(options =>
|
|
||||||
{
|
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
|
||||||
ValidateIssuer = true,
|
|
||||||
ValidateAudience = true,
|
|
||||||
ValidateLifetime = true,
|
|
||||||
ValidateIssuerSigningKey = true,
|
|
||||||
ValidIssuer = jwtOptions.Issuer,
|
|
||||||
ValidAudience = jwtOptions.Audience,
|
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SigningKey)),
|
|
||||||
ClockSkew = TimeSpan.FromMinutes(1),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
services.AddAuthorization();
|
|
||||||
services.AddScoped<JwtTokenService>();
|
|
||||||
services.AddScoped<RefreshTokenService>();
|
|
||||||
services.AddScoped<IApiAuthEndpointService, ApiAuthEndpointService>();
|
|
||||||
|
|
||||||
// ---- 统一端点 ----
|
|
||||||
var endpointBuilder = new ServiceEndpointBuilder();
|
|
||||||
AppEndpoints.Configure(endpointBuilder);
|
|
||||||
AuthEndpoints.ConfigureApi(endpointBuilder);
|
|
||||||
var endpoints = endpointBuilder.Build();
|
|
||||||
services.AddSingleton(endpoints);
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
using FileShare_Services.Services.FileLibrary;
|
|
||||||
|
|
||||||
namespace FileShare_API.Extensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// API-only raw file stream endpoints used by browser media elements.
|
|
||||||
/// </summary>
|
|
||||||
public static class FileStreamEndpointExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Map the media URL emitted by <see cref="FileRecordDto"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static IEndpointRouteBuilder MapFileStreamEndpoints(this IEndpointRouteBuilder app)
|
|
||||||
{
|
|
||||||
app.MapMethods(
|
|
||||||
"/api/files/{id:int}/stream",
|
|
||||||
["GET", "HEAD"],
|
|
||||||
async (int id, IFileStreamService fileStreamService, HttpContext httpContext) =>
|
|
||||||
{
|
|
||||||
var fileResponse = await fileStreamService.GetFileStreamAsync(id);
|
|
||||||
if (fileResponse is null)
|
|
||||||
{
|
|
||||||
return Results.NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var stream = System.IO.File.Open(
|
|
||||||
fileResponse.FilePath,
|
|
||||||
FileMode.Open,
|
|
||||||
FileAccess.Read,
|
|
||||||
FileShare.ReadWrite);
|
|
||||||
|
|
||||||
httpContext.Response.Headers.ContentDisposition =
|
|
||||||
$"inline; filename=\"{Uri.EscapeDataString(fileResponse.FileName)}\"";
|
|
||||||
httpContext.Response.Headers.AcceptRanges = "bytes";
|
|
||||||
httpContext.Response.Headers.CacheControl = "public, max-age=3600";
|
|
||||||
|
|
||||||
return Results.File(
|
|
||||||
stream,
|
|
||||||
contentType: fileResponse.ContentType,
|
|
||||||
lastModified: fileResponse.LastModified,
|
|
||||||
enableRangeProcessing: true);
|
|
||||||
})
|
|
||||||
.WithName("StreamManagedFileById")
|
|
||||||
.WithTags("FileLibrary");
|
|
||||||
|
|
||||||
app.MapMethods(
|
|
||||||
"/api/thumbnails/{id:int}",
|
|
||||||
["GET", "HEAD"],
|
|
||||||
async (int id, IThumbnailStreamService thumbnailStreamService, HttpContext httpContext) =>
|
|
||||||
{
|
|
||||||
var thumbnail = await thumbnailStreamService.GetThumbnailAsync(id);
|
|
||||||
if (thumbnail is null)
|
|
||||||
{
|
|
||||||
return Results.NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var stream = System.IO.File.Open(
|
|
||||||
thumbnail.FilePath,
|
|
||||||
FileMode.Open,
|
|
||||||
FileAccess.Read,
|
|
||||||
FileShare.ReadWrite);
|
|
||||||
|
|
||||||
httpContext.Response.Headers.ContentDisposition =
|
|
||||||
$"inline; filename=\"{Uri.EscapeDataString(thumbnail.FileName)}\"";
|
|
||||||
httpContext.Response.Headers.CacheControl = "public, max-age=3600";
|
|
||||||
|
|
||||||
return Results.File(
|
|
||||||
stream,
|
|
||||||
contentType: thumbnail.ContentType,
|
|
||||||
lastModified: thumbnail.LastModified);
|
|
||||||
})
|
|
||||||
.WithName("StreamManagedThumbnailById")
|
|
||||||
.WithTags("FileLibrary");
|
|
||||||
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,254 +0,0 @@
|
|||||||
using FileShare_Services.Core;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using AspNetCoreFilterContext = Microsoft.AspNetCore.Http.EndpointFilterInvocationContext;
|
|
||||||
using AspNetCoreFilterDelegate = Microsoft.AspNetCore.Http.EndpointFilterDelegate;
|
|
||||||
// 解决与 ASP.NET Core 同名类型的冲突
|
|
||||||
using UnifiedFilter = FileShare_Services.Core.IEndpointFilter;
|
|
||||||
|
|
||||||
namespace FileShare_API.Extensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 将 FileShare-Services 的统一端点映射到 ASP.NET Core Minimal API。
|
|
||||||
/// 支持鉴权、过滤器、中间件的完整 ASP.NET Core 管道。
|
|
||||||
/// </summary>
|
|
||||||
public static class UnifiedEndpointExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 将 ServiceEndpointCollection 中的所有端点注册到 ASP.NET Core 路由。
|
|
||||||
/// </summary>
|
|
||||||
public static IEndpointRouteBuilder MapUnifiedEndpoints(
|
|
||||||
this IEndpointRouteBuilder routeBuilder,
|
|
||||||
ServiceEndpointCollection endpoints,
|
|
||||||
IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
var apiGroup = routeBuilder.MapGroup("/");
|
|
||||||
|
|
||||||
foreach (var endpoint in endpoints.ForHost(EndpointHostTarget.Api))
|
|
||||||
{
|
|
||||||
var routeHandlerBuilder = MapEndpoint(apiGroup, endpoint, serviceProvider);
|
|
||||||
|
|
||||||
// 全局过滤器 → ASP.NET Core Endpoint Filters
|
|
||||||
foreach (var globalFilter in endpoints.GlobalFilters)
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.AddEndpointFilter(
|
|
||||||
async (context, next) => await ConvertFilterAsync(globalFilter, context, next));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 端点专属过滤器
|
|
||||||
foreach (var filter in endpoint.Filters)
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.AddEndpointFilter(
|
|
||||||
async (context, next) => await ConvertFilterAsync(filter, context, next));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 鉴权(使用 ASP.NET Core 原生鉴权机制)
|
|
||||||
if (endpoint.RequireAuthorization)
|
|
||||||
{
|
|
||||||
if (endpoint.Roles.Count > 0)
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.RequireAuthorization(new AuthorizeAttribute
|
|
||||||
{
|
|
||||||
Roles = string.Join(',', endpoint.Roles),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (!string.IsNullOrEmpty(endpoint.Policy))
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.RequireAuthorization(endpoint.Policy);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.RequireAuthorization();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(endpoint.Name))
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.WithName(endpoint.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(endpoint.OpenApiTag))
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.WithTags(endpoint.OpenApiTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(endpoint.OpenApiDescription))
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.WithDescription(endpoint.OpenApiDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(endpoint.OpenApiSummary))
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.WithSummary(endpoint.OpenApiSummary);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endpoint.OpenApiRequestType is not null
|
|
||||||
&& endpoint.HttpMethod is "POST" or "PUT")
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.Accepts(endpoint.OpenApiRequestType, "application/json");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endpoint.OpenApiResponseType is not null)
|
|
||||||
{
|
|
||||||
routeHandlerBuilder.Produces(200, endpoint.OpenApiResponseType, "application/json");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return routeBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据端点的 HTTP 方法(GET/POST/PUT/DELETE)将其映射到 ASP.NET Core 路由。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="group">路由组。</param>
|
|
||||||
/// <param name="endpoint">统一端点定义。</param>
|
|
||||||
/// <param name="serviceProvider">服务提供程序。</param>
|
|
||||||
/// <returns>路由处理器构建器,用于叠加过滤器等配置。</returns>
|
|
||||||
private static RouteHandlerBuilder MapEndpoint(
|
|
||||||
IEndpointRouteBuilder group,
|
|
||||||
ServiceEndpoint endpoint,
|
|
||||||
IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
var handler = CreateAspNetCoreHandler(endpoint.Handler, serviceProvider);
|
|
||||||
|
|
||||||
return endpoint.HttpMethod.ToUpperInvariant() switch
|
|
||||||
{
|
|
||||||
"GET" => group.MapGet(endpoint.Pattern, handler),
|
|
||||||
"POST" => group.MapPost(endpoint.Pattern, handler),
|
|
||||||
"PUT" => group.MapPut(endpoint.Pattern, handler),
|
|
||||||
"DELETE" => group.MapDelete(endpoint.Pattern, handler),
|
|
||||||
_ => group.MapGet(endpoint.Pattern, handler),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建适配 ASP.NET Core 的委托处理器,将统一处理器包装为 ASP.NET Core 可识别的委托。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="unifiedHandler">统一端点处理器。</param>
|
|
||||||
/// <param name="serviceProvider">服务提供程序。</param>
|
|
||||||
/// <returns>ASP.NET Core 兼容的委托。</returns>
|
|
||||||
private static Delegate CreateAspNetCoreHandler(
|
|
||||||
Func<ServiceEndpointContext, Task<object?>> unifiedHandler,
|
|
||||||
IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
return async (HttpContext httpContext) =>
|
|
||||||
{
|
|
||||||
var ctx = httpContext.Items["UnifiedContext"] as ServiceEndpointContext
|
|
||||||
?? await BuildContextFromHttpContext(httpContext);
|
|
||||||
ctx.Items["ServiceProvider"] = serviceProvider;
|
|
||||||
ctx.Items["User"] = httpContext.User;
|
|
||||||
httpContext.Items["UnifiedContext"] = ctx;
|
|
||||||
|
|
||||||
var result = await unifiedHandler(ctx);
|
|
||||||
|
|
||||||
// 同步响应状态
|
|
||||||
httpContext.Response.StatusCode = ctx.StatusCode;
|
|
||||||
foreach (var kvp in ctx.ResponseHeaders)
|
|
||||||
{
|
|
||||||
httpContext.Response.Headers[kvp.Key] = kvp.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result is FileStreamResponse fileResponse)
|
|
||||||
{
|
|
||||||
if (!System.IO.File.Exists(fileResponse.FilePath))
|
|
||||||
return Results.NotFound();
|
|
||||||
|
|
||||||
var stream = System.IO.File.Open(fileResponse.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
|
||||||
httpContext.Response.Headers.ContentDisposition = $"inline; filename=\"{Uri.EscapeDataString(fileResponse.FileName)}\"";
|
|
||||||
httpContext.Response.Headers.AcceptRanges = "bytes";
|
|
||||||
httpContext.Response.Headers.CacheControl = "public, max-age=3600";
|
|
||||||
|
|
||||||
return Results.File(
|
|
||||||
stream,
|
|
||||||
contentType: fileResponse.ContentType,
|
|
||||||
lastModified: fileResponse.LastModified,
|
|
||||||
enableRangeProcessing: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result is not null ? Results.Json(result) : Results.Ok();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从 ASP.NET Core 的 HttpContext 构建统一的 ServiceEndpointContext,
|
|
||||||
/// 提取路径、方法、请求头、查询参数和请求体。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpContext">ASP.NET Core 的 HttpContext。</param>
|
|
||||||
/// <returns>构建好的统一端点上下文。</returns>
|
|
||||||
private static async Task<ServiceEndpointContext> BuildContextFromHttpContext(HttpContext httpContext)
|
|
||||||
{
|
|
||||||
var ctx = new ServiceEndpointContext
|
|
||||||
{
|
|
||||||
Path = httpContext.Request.Path.Value ?? "/",
|
|
||||||
Method = httpContext.Request.Method,
|
|
||||||
StatusCode = 200,
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var header in httpContext.Request.Headers)
|
|
||||||
{
|
|
||||||
ctx.Headers[header.Key] = header.Value.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var query in httpContext.Request.Query)
|
|
||||||
{
|
|
||||||
ctx.Query[query.Key] = query.Value.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var routeValue in httpContext.Request.RouteValues)
|
|
||||||
{
|
|
||||||
if (routeValue.Value is not null)
|
|
||||||
{
|
|
||||||
ctx.RouteValues[routeValue.Key] = routeValue.Value.ToString() ?? string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (httpContext.Request.ContentLength > 0)
|
|
||||||
{
|
|
||||||
using var reader = new StreamReader(httpContext.Request.Body);
|
|
||||||
ctx.Body = await reader.ReadToEndAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Items["HttpContext"] = httpContext;
|
|
||||||
ctx.Items["User"] = httpContext.User;
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 将统一过滤器转换为 ASP.NET Core 端点过滤器,
|
|
||||||
/// 在调用统一过滤器前后桥接上下文和状态。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="unifiedFilter">统一过滤器。</param>
|
|
||||||
/// <param name="aspContext">ASP.NET Core 过滤器调用上下文。</param>
|
|
||||||
/// <param name="aspNext">ASP.NET Core 过滤器管道中的下一个委托。</param>
|
|
||||||
/// <returns>过滤器执行结果,可能包含短路响应体。</returns>
|
|
||||||
private static async ValueTask<object?> ConvertFilterAsync(
|
|
||||||
UnifiedFilter unifiedFilter,
|
|
||||||
AspNetCoreFilterContext aspContext,
|
|
||||||
AspNetCoreFilterDelegate aspNext)
|
|
||||||
{
|
|
||||||
var httpContext = aspContext.HttpContext;
|
|
||||||
var ctx = httpContext.Items["UnifiedContext"] as ServiceEndpointContext
|
|
||||||
?? await BuildContextFromHttpContext(httpContext);
|
|
||||||
|
|
||||||
httpContext.Items["UnifiedContext"] = ctx;
|
|
||||||
|
|
||||||
object? nextResult = null;
|
|
||||||
await unifiedFilter.InvokeAsync(ctx, async (c) =>
|
|
||||||
{
|
|
||||||
httpContext.Response.StatusCode = c.StatusCode;
|
|
||||||
foreach (var kvp in c.ResponseHeaders)
|
|
||||||
{
|
|
||||||
httpContext.Response.Headers[kvp.Key] = kvp.Value;
|
|
||||||
}
|
|
||||||
nextResult = await aspNext(aspContext);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ctx.ResponseBody is not null)
|
|
||||||
{
|
|
||||||
return Results.Json(ctx.ResponseBody, statusCode: ctx.StatusCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nextResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<RootNamespace>FileShare_API</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.5" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.5" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.4" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\FileShare-Services\FileShare-Services.csproj" />
|
|
||||||
<ProjectReference Include="..\FileShare-Common\FileShare-Common.csproj" />
|
|
||||||
<ProjectReference Include="..\FileShare-EFCore\FileShare-EFCore.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Controllers\" />
|
|
||||||
<Content Include="..\tools\ffmpeg\bin\ffmpeg.exe" Link="tools\ffmpeg\bin\ffmpeg.exe" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
|
||||||
<Content Include="..\tools\ffmpeg\bin\ffprobe.exe" Link="tools\ffmpeg\bin\ffprobe.exe" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="RestoreFrontendPackages" BeforeTargets="Build" Condition="'$(SkipFrontendBuild)' != 'true' And Exists('..\FileShare-Web-VUE\package.json') And !Exists('..\FileShare-Web-VUE\node_modules')">
|
|
||||||
<Message Importance="high" Text="Restoring FileShare-Web-VUE npm packages..." />
|
|
||||||
<Exec WorkingDirectory="..\FileShare-Web-VUE" Command="npm.cmd install" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="BuildFrontend" BeforeTargets="Build" DependsOnTargets="RestoreFrontendPackages" Condition="'$(SkipFrontendBuild)' != 'true' And Exists('..\FileShare-Web-VUE\package.json')">
|
|
||||||
<Message Importance="high" Text="Building FileShare-Web-VUE into FileShare-API/wwwroot..." />
|
|
||||||
<Exec WorkingDirectory="..\FileShare-Web-VUE" Command="npm.cmd run build-only" />
|
|
||||||
<RemoveDir Directories="wwwroot" />
|
|
||||||
<MakeDir Directories="wwwroot" />
|
|
||||||
<ItemGroup>
|
|
||||||
<FrontendDist Include="..\FileShare-Web-VUE\dist\**\*.*" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Copy SourceFiles="@(FrontendDist)" DestinationFiles="@(FrontendDist->'wwwroot\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<ActiveDebugProfile>http</ActiveDebugProfile>
|
|
||||||
<NameOfLastUsedPublishProfile>D:\Project\FileShare\FileShare-API\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
|
||||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
@FileShare_API_HostAddress = http://localhost:5206
|
|
||||||
|
|
||||||
GET {{FileShare_API_HostAddress}}/weatherforecast/
|
|
||||||
Accept: application/json
|
|
||||||
|
|
||||||
###
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
using FileShare_API.Configuration;
|
|
||||||
using FileShare_API.Extensions;
|
|
||||||
using FileShare_Common.Infrastructure;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using FileShare_Services.Core;
|
|
||||||
using Serilog;
|
|
||||||
|
|
||||||
// 初始化日志系统
|
|
||||||
Log.Logger = LoggingConfiguration.CreateDefaultLogger(logDir: "logs");
|
|
||||||
Log.Information("FileShare-API 正在启动...");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
|
||||||
|
|
||||||
// 配置 Kestrel 监听所有本机 IP(端口从 Server 配置节读取)
|
|
||||||
var httpPort = builder.Configuration.GetValue<int>("Server:HttpPort", 5206);
|
|
||||||
var httpsPort = builder.Configuration.GetValue<int>("Server:HttpsPort", 7165);
|
|
||||||
builder.WebHost.UseUrls($"http://0.0.0.0:{httpPort}", $"https://0.0.0.0:{httpsPort}");
|
|
||||||
|
|
||||||
// 使用 Serilog 作为日志提供程序
|
|
||||||
builder.Host.UseSerilog();
|
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
builder.Services.AddControllers();
|
|
||||||
builder.Services.AddOpenApi();
|
|
||||||
builder.Services.AddCors(options =>
|
|
||||||
{
|
|
||||||
options.AddPolicy("LanFileViewer", policy =>
|
|
||||||
policy.AllowAnyOrigin()
|
|
||||||
.AllowAnyHeader()
|
|
||||||
.AllowAnyMethod());
|
|
||||||
});
|
|
||||||
|
|
||||||
// 注册统一端点及业务服务(入口在 FileShare-Services/Endpoints/AppEndpoints.cs)
|
|
||||||
builder.Services.AddUnifiedApiServices(builder.Configuration);
|
|
||||||
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
// 初始化数据库(自动迁移 + 种子数据)
|
|
||||||
app.Services.InitializeDatabase<AppDataContext>();
|
|
||||||
|
|
||||||
var endpoints = app.Services.GetRequiredService<ServiceEndpointCollection>();
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
if (app.Environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.MapOpenApi();
|
|
||||||
app.UseSwaggerUI(options =>
|
|
||||||
{
|
|
||||||
options.SwaggerEndpoint("/openapi/v1.json", "FileShare API v1");
|
|
||||||
options.RoutePrefix = "swagger";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseDefaultFiles();
|
|
||||||
app.UseStaticFiles();
|
|
||||||
// 局域网文件播放优先使用 HTTP,避免手机浏览器对自签 HTTPS/HTTP2 视频流的兼容问题。
|
|
||||||
app.UseCors("LanFileViewer");
|
|
||||||
app.UseAuthentication();
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
// 将统一端点映射到 ASP.NET Core 路由
|
|
||||||
app.MapUnifiedEndpoints(endpoints, app.Services);
|
|
||||||
app.MapFileStreamEndpoints();
|
|
||||||
app.MapFallbackToFile("index.html");
|
|
||||||
|
|
||||||
app.Run();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Fatal(ex, "FileShare-API 启动失败");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Log.CloseAndFlush();
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
|
||||||
"profiles": {
|
|
||||||
"http": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": false,
|
|
||||||
"applicationUrl": "http://0.0.0.0:5206",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": false,
|
|
||||||
"applicationUrl": "https://0.0.0.0:7165;http://0.0.0.0:5206",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
using FileShare_Services.Services.FileLibrary;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
|
|
||||||
namespace FileShare_API.Services
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 文件库定时扫描后台服务,按配置间隔检查是否有需要扫描的文件库目录。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class FileLibraryScanHostedService(
|
|
||||||
IServiceScopeFactory scopeFactory,
|
|
||||||
IOptions<FileLibraryScanOptions> options,
|
|
||||||
ILogger<FileLibraryScanHostedService> logger)
|
|
||||||
: BackgroundService
|
|
||||||
{
|
|
||||||
/// <summary>后台服务检查到期扫描任务的轮询间隔。</summary>
|
|
||||||
private readonly TimeSpan _interval = TimeSpan.FromMinutes(Math.Max(1, options.Value.PollingIntervalMinutes));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启动扫描循环,首次立即执行,之后按配置的轮询间隔重复执行。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stoppingToken">应用关闭时触发的取消令牌。</param>
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
||||||
{
|
|
||||||
logger.LogInformation("文件库定时扫描服务已启动,轮询间隔 {IntervalMinutes} 分钟。", _interval.TotalMinutes);
|
|
||||||
await ScanAsync(stoppingToken);
|
|
||||||
|
|
||||||
using var timer = new PeriodicTimer(_interval);
|
|
||||||
while (await timer.WaitForNextTickAsync(stoppingToken))
|
|
||||||
{
|
|
||||||
await ScanAsync(stoppingToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建临时作用域并调用 <see cref="IFileLibraryService.ScanDueRootsAsync"/> 执行一次到期扫描。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cancellationToken">取消令牌。</param>
|
|
||||||
private async Task ScanAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var startedAt = DateTime.UtcNow;
|
|
||||||
logger.LogInformation("文件库定时扫描轮询开始。");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await using var scope = scopeFactory.CreateAsyncScope();
|
|
||||||
var scanner = scope.ServiceProvider.GetRequiredService<IFileLibraryService>();
|
|
||||||
await scanner.ScanDueRootsAsync(cancellationToken);
|
|
||||||
logger.LogInformation(
|
|
||||||
"文件库定时扫描轮询完成,耗时 {ElapsedMilliseconds} ms。",
|
|
||||||
(DateTime.UtcNow - startedAt).TotalMilliseconds);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
logger.LogInformation("文件库定时扫描轮询已取消。");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
logger.LogWarning(ex, "文件库定时扫描失败。");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
namespace FileShare_API.Services
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 文件库定时扫描后台服务配置。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class FileLibraryScanOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 后台服务检查到期文件库目录的轮询间隔分钟数。
|
|
||||||
/// </summary>
|
|
||||||
public int PollingIntervalMinutes { get; set; } = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AllowedHosts": "*",
|
|
||||||
"Server": {
|
|
||||||
"HttpPort": 5206,
|
|
||||||
"HttpsPort": 7165
|
|
||||||
},
|
|
||||||
"Jwt": {
|
|
||||||
"Issuer": "FileShare-API",
|
|
||||||
"Audience": "FileShare-Client",
|
|
||||||
"SigningKey": "change-this-development-signing-key-at-least-32-bytes",
|
|
||||||
"AccessTokenMinutes": 60,
|
|
||||||
"RefreshTokenDays": 30
|
|
||||||
},
|
|
||||||
"DatabaseConfiguration": {
|
|
||||||
"Provider": "SQLite",
|
|
||||||
"ConnectionString": "Data Source=app.db",
|
|
||||||
"AutoMigrate": true,
|
|
||||||
"RecreateDatabase": false,
|
|
||||||
"EnableDetailedLog": false,
|
|
||||||
"Timeout": 30
|
|
||||||
},
|
|
||||||
"ThumbnailStorageOptions": {
|
|
||||||
"RootPath": "thumbnails",
|
|
||||||
"FfmpegPath": "tools/ffmpeg/bin/ffmpeg.exe",
|
|
||||||
"FfprobePath": "tools/ffmpeg/bin/ffprobe.exe"
|
|
||||||
},
|
|
||||||
"FileLibraryScanOptions": {
|
|
||||||
"PollingIntervalMinutes": 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,217 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace FileShare_Common.Core
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 统一端点响应契约。
|
|
||||||
/// </summary>
|
|
||||||
public interface IApiResponse
|
|
||||||
{
|
|
||||||
/// <summary>是否成功。</summary>
|
|
||||||
bool Success { get; }
|
|
||||||
|
|
||||||
/// <summary>业务状态码。</summary>
|
|
||||||
int Code { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 统一 API 返回格式。
|
|
||||||
/// 所有接口的返回都包装为此格式,确保前端收到一致的数据结构。
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">业务数据类型</typeparam>
|
|
||||||
public class ApiResponse<T> : IApiResponse
|
|
||||||
{
|
|
||||||
/// <summary>是否成功</summary>
|
|
||||||
[JsonPropertyName("success")]
|
|
||||||
public bool Success { get; set; }
|
|
||||||
|
|
||||||
/// <summary>HTTP 状态码</summary>
|
|
||||||
[JsonPropertyName("code")]
|
|
||||||
public int Code { get; set; }
|
|
||||||
|
|
||||||
/// <summary>消息(成功时可为 null,失败时包含错误描述)</summary>
|
|
||||||
[JsonPropertyName("message")]
|
|
||||||
public string? Message { get; set; }
|
|
||||||
|
|
||||||
/// <summary>业务数据</summary>
|
|
||||||
[JsonPropertyName("data")]
|
|
||||||
public T? Data { get; set; }
|
|
||||||
|
|
||||||
/// <summary>时间戳</summary>
|
|
||||||
[JsonPropertyName("timestamp")]
|
|
||||||
public DateTime Timestamp { get; set; } = DateTime.Now;
|
|
||||||
|
|
||||||
/// <summary>请求追踪 ID(用于排查问题)</summary>
|
|
||||||
[JsonPropertyName("traceId")]
|
|
||||||
public string? TraceId { get; set; }
|
|
||||||
|
|
||||||
// ---- 快捷工厂方法 ----
|
|
||||||
|
|
||||||
/// <summary>成功返回(有数据)</summary>
|
|
||||||
public static ApiResponse<T> Ok(T data, string? message = null)
|
|
||||||
{
|
|
||||||
return new ApiResponse<T>
|
|
||||||
{
|
|
||||||
Success = true,
|
|
||||||
Code = 200,
|
|
||||||
Message = message,
|
|
||||||
Data = data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>失败返回</summary>
|
|
||||||
public static ApiResponse<T> Fail(int code, string message, T? data = default)
|
|
||||||
{
|
|
||||||
return new ApiResponse<T>
|
|
||||||
{
|
|
||||||
Success = false,
|
|
||||||
Code = code,
|
|
||||||
Message = message,
|
|
||||||
Data = data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>400 参数错误</summary>
|
|
||||||
public static ApiResponse<T> BadRequest(string message = "参数错误")
|
|
||||||
=> Fail(400, message);
|
|
||||||
|
|
||||||
/// <summary>401 未授权</summary>
|
|
||||||
public static ApiResponse<T> Unauthorized(string message = "未授权")
|
|
||||||
=> Fail(401, message);
|
|
||||||
|
|
||||||
/// <summary>403 无权限</summary>
|
|
||||||
public static ApiResponse<T> Forbidden(string message = "无权限")
|
|
||||||
=> Fail(403, message);
|
|
||||||
|
|
||||||
/// <summary>404 未找到</summary>
|
|
||||||
public static ApiResponse<T> NotFound(string message = "资源不存在")
|
|
||||||
=> Fail(404, message);
|
|
||||||
|
|
||||||
/// <summary>500 服务器内部错误</summary>
|
|
||||||
public static ApiResponse<T> ServerError(string message = "服务器内部错误")
|
|
||||||
=> Fail(500, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 无数据的统一返回格式(object? 版本)。
|
|
||||||
/// </summary>
|
|
||||||
public class ApiResponse : ApiResponse<object?>
|
|
||||||
{
|
|
||||||
/// <summary>成功返回(无数据)</summary>
|
|
||||||
public static ApiResponse Succeed(string? message = null)
|
|
||||||
{
|
|
||||||
return new ApiResponse
|
|
||||||
{
|
|
||||||
Success = true,
|
|
||||||
Code = 200,
|
|
||||||
Message = message,
|
|
||||||
Data = null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>失败返回</summary>
|
|
||||||
public static ApiResponse Failure(int code, string message)
|
|
||||||
{
|
|
||||||
return new ApiResponse
|
|
||||||
{
|
|
||||||
Success = false,
|
|
||||||
Code = code,
|
|
||||||
Message = message,
|
|
||||||
Data = null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 分页返回格式
|
|
||||||
/// </summary>
|
|
||||||
public class PagedResponse<T> : IApiResponse
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置操作是否成功。
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("success")]
|
|
||||||
public bool Success { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置业务状态码,默认 200。
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("code")]
|
|
||||||
public int Code { get; set; } = 200;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置分页数据项列表。
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("items")]
|
|
||||||
public List<T> Items { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置数据总条数。
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("total")]
|
|
||||||
public int Total { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置当前页码,从 1 开始。
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("page")]
|
|
||||||
public int Page { get; set; } = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置每页条数,默认 20。
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("pageSize")]
|
|
||||||
public int PageSize { get; set; } = 20;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取总页数(根据 Total 和 PageSize 自动计算)。
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("totalPages")]
|
|
||||||
public int TotalPages => PageSize > 0 ? (int)Math.Ceiling((double)Total / PageSize) : 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从数据列表和分页参数创建分页响应。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="items">当前页数据项。</param>
|
|
||||||
/// <param name="total">数据总条数。</param>
|
|
||||||
/// <param name="page">当前页码。</param>
|
|
||||||
/// <param name="pageSize">每页条数。</param>
|
|
||||||
/// <returns>分页响应实例。</returns>
|
|
||||||
public static PagedResponse<T> From(List<T> items, int total, int page, int pageSize)
|
|
||||||
{
|
|
||||||
return new PagedResponse<T>
|
|
||||||
{
|
|
||||||
Items = items,
|
|
||||||
Total = total,
|
|
||||||
Page = page,
|
|
||||||
PageSize = pageSize,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 端点返回辅助方法 —— 在 AppEndpoints 中快捷构建统一响应。
|
|
||||||
/// </summary>
|
|
||||||
public static class ResponseHelper
|
|
||||||
{
|
|
||||||
/// <summary>成功返回</summary>
|
|
||||||
public static ApiResponse<T> Ok<T>(T data, string? message = null)
|
|
||||||
=> ApiResponse<T>.Ok(data, message);
|
|
||||||
|
|
||||||
/// <summary>成功返回(无数据)</summary>
|
|
||||||
public static ApiResponse Succeed(string? message = null)
|
|
||||||
=> ApiResponse.Succeed(message);
|
|
||||||
|
|
||||||
/// <summary>失败返回</summary>
|
|
||||||
public static ApiResponse<T> Fail<T>(int code, string message, T? data = default)
|
|
||||||
=> ApiResponse<T>.Fail(code, message, data);
|
|
||||||
|
|
||||||
/// <summary>失败返回(无数据)</summary>
|
|
||||||
public static ApiResponse Failure(int code, string message)
|
|
||||||
=> ApiResponse.Failure(code, message);
|
|
||||||
|
|
||||||
/// <summary>分页返回</summary>
|
|
||||||
public static PagedResponse<T> Paged<T>(List<T> items, int total, int page, int pageSize)
|
|
||||||
=> PagedResponse<T>.From(items, total, page, pageSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
|
||||||
<RootNamespace>FileShare_Common</RootNamespace>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Serilog" Version="4.2.0" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
|
|
||||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@ -1,167 +0,0 @@
|
|||||||
using Serilog;
|
|
||||||
using Serilog.Events;
|
|
||||||
|
|
||||||
namespace FileShare_Common.Infrastructure
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Serilog 日志配置 —— 可在 FileShare-API 和 FileShare-PC 中共享。
|
|
||||||
/// </summary>
|
|
||||||
public static class LoggingConfiguration
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 默认日志目录
|
|
||||||
/// </summary>
|
|
||||||
private static readonly string DefaultLogDir = Path.Combine(AppContext.BaseDirectory, "logs");
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建控制台日志记录器(开发环境)。
|
|
||||||
/// </summary>
|
|
||||||
public static ILogger CreateConsoleLogger(
|
|
||||||
LogEventLevel minimumLevel = LogEventLevel.Debug)
|
|
||||||
{
|
|
||||||
return new LoggerConfiguration()
|
|
||||||
.MinimumLevel.Is(minimumLevel)
|
|
||||||
.Enrich.FromLogContext()
|
|
||||||
.WriteTo.Console(
|
|
||||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
|
|
||||||
.CreateLogger();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建控制台 + 文件日志记录器。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="minimumLevel">最低日志级别</param>
|
|
||||||
/// <param name="logDir">日志目录,默认 ./logs</param>
|
|
||||||
/// <param name="retainedDays">保留天数</param>
|
|
||||||
public static ILogger CreateDefaultLogger(
|
|
||||||
LogEventLevel minimumLevel = LogEventLevel.Information,
|
|
||||||
string? logDir = null,
|
|
||||||
int retainedDays = 30)
|
|
||||||
{
|
|
||||||
logDir ??= DefaultLogDir;
|
|
||||||
|
|
||||||
return new LoggerConfiguration()
|
|
||||||
.MinimumLevel.Is(minimumLevel)
|
|
||||||
//.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
|
||||||
//.MinimumLevel.Override("System", LogEventLevel.Warning)
|
|
||||||
.Enrich.FromLogContext()
|
|
||||||
.Enrich.WithMachineName()
|
|
||||||
.Enrich.WithThreadId()
|
|
||||||
.WriteTo.Console(
|
|
||||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
|
|
||||||
.WriteTo.File(
|
|
||||||
path: Path.Combine(logDir, "log-.txt"),
|
|
||||||
rollingInterval: RollingInterval.Day,
|
|
||||||
retainedFileCountLimit: retainedDays,
|
|
||||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
|
||||||
encoding: System.Text.Encoding.UTF8)
|
|
||||||
.CreateLogger();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建只写文件的日志记录器(桌面应用静默模式)。
|
|
||||||
/// </summary>
|
|
||||||
public static ILogger CreateFileOnlyLogger(
|
|
||||||
LogEventLevel minimumLevel = LogEventLevel.Information,
|
|
||||||
string? logDir = null,
|
|
||||||
int retainedDays = 30)
|
|
||||||
{
|
|
||||||
logDir ??= DefaultLogDir;
|
|
||||||
|
|
||||||
return new LoggerConfiguration()
|
|
||||||
.MinimumLevel.Is(minimumLevel)
|
|
||||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
|
||||||
.Enrich.FromLogContext()
|
|
||||||
.WriteTo.File(
|
|
||||||
path: Path.Combine(logDir, "app-.txt"),
|
|
||||||
rollingInterval: RollingInterval.Day,
|
|
||||||
retainedFileCountLimit: retainedDays,
|
|
||||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
|
||||||
encoding: System.Text.Encoding.UTF8)
|
|
||||||
.CreateLogger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 静态日志访问器 —— 全局静态入口,方便在没有 DI 的场景下使用。
|
|
||||||
/// </summary>
|
|
||||||
public static class AppLog
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 保存全局日志记录器实例。
|
|
||||||
/// </summary>
|
|
||||||
private static ILogger? _logger;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化全局日志记录器。
|
|
||||||
/// </summary>
|
|
||||||
public static void Initialize(ILogger logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
Log.Logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取全局日志记录器。若未初始化则回退到 Serilog.Log.Logger。
|
|
||||||
/// </summary>
|
|
||||||
public static ILogger Logger => _logger ?? Log.Logger;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入 Debug 级别日志。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">消息模板。</param>
|
|
||||||
/// <param name="propertyValues">属性值。</param>
|
|
||||||
public static void Debug(string messageTemplate, params object?[] propertyValues)
|
|
||||||
=> Logger.Debug(messageTemplate, propertyValues);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入 Information 级别日志。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">消息模板。</param>
|
|
||||||
/// <param name="propertyValues">属性值。</param>
|
|
||||||
public static void Information(string messageTemplate, params object?[] propertyValues)
|
|
||||||
=> Logger.Information(messageTemplate, propertyValues);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入 Warning 级别日志。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">消息模板。</param>
|
|
||||||
/// <param name="propertyValues">属性值。</param>
|
|
||||||
public static void Warning(string messageTemplate, params object?[] propertyValues)
|
|
||||||
=> Logger.Warning(messageTemplate, propertyValues);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入 Error 级别日志。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">消息模板。</param>
|
|
||||||
/// <param name="propertyValues">属性值。</param>
|
|
||||||
public static void Error(string messageTemplate, params object?[] propertyValues)
|
|
||||||
=> Logger.Error(messageTemplate, propertyValues);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入 Error 级别日志,并附带异常信息。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">异常对象。</param>
|
|
||||||
/// <param name="messageTemplate">消息模板。</param>
|
|
||||||
/// <param name="propertyValues">属性值。</param>
|
|
||||||
public static void Error(Exception exception, string messageTemplate, params object?[] propertyValues)
|
|
||||||
=> Logger.Error(exception, messageTemplate, propertyValues);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入 Fatal 级别日志。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">消息模板。</param>
|
|
||||||
/// <param name="propertyValues">属性值。</param>
|
|
||||||
public static void Fatal(string messageTemplate, params object?[] propertyValues)
|
|
||||||
=> Logger.Fatal(messageTemplate, propertyValues);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入 Fatal 级别日志,并附带异常信息。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">异常对象。</param>
|
|
||||||
/// <param name="messageTemplate">消息模板。</param>
|
|
||||||
/// <param name="propertyValues">属性值。</param>
|
|
||||||
public static void Fatal(Exception exception, string messageTemplate, params object?[] propertyValues)
|
|
||||||
=> Logger.Fatal(exception, messageTemplate, propertyValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
using FileShare_EFCore.Models;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 应用数据库上下文 —— 继承自 FileShare-EFCore 的 AppDbContext。
|
|
||||||
/// 所有业务实体在此注册 DbSet。
|
|
||||||
/// 这是 FileShare-API 和 FileShare-PC 共用的具体数据上下文。
|
|
||||||
/// </summary>
|
|
||||||
public class AppDataContext(DatabaseConfiguration dbConfig) : AppDbContext(dbConfig)
|
|
||||||
{
|
|
||||||
/// <summary>天气预报数据</summary>
|
|
||||||
public DbSet<WeatherForecastEntity> WeatherForecasts => Set<WeatherForecastEntity>();
|
|
||||||
|
|
||||||
/// <summary>用户数据</summary>
|
|
||||||
public DbSet<UserEntity> Users => Set<UserEntity>();
|
|
||||||
|
|
||||||
/// <summary>API refresh token 数据</summary>
|
|
||||||
public DbSet<ApiRefreshTokenEntity> ApiRefreshTokens => Set<ApiRefreshTokenEntity>();
|
|
||||||
|
|
||||||
/// <summary>文件库根目录数据</summary>
|
|
||||||
public DbSet<ManagedLibraryRoot> ManagedLibraryRoots => Set<ManagedLibraryRoot>();
|
|
||||||
|
|
||||||
/// <summary>文件库文件记录数据</summary>
|
|
||||||
public DbSet<ManagedFileRecord> ManagedFileRecords => Set<ManagedFileRecord>();
|
|
||||||
|
|
||||||
/// <summary>文件缩略图映射数据</summary>
|
|
||||||
public DbSet<ManagedThumbnailMap> ManagedThumbnailMaps => Set<ManagedThumbnailMap>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 配置实体映射,包括主键、索引和属性约束。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="modelBuilder">模型构建器。</param>
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity<WeatherForecastEntity>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id).HasName("pk-weather-forecast");
|
|
||||||
entity.Property(e => e.Summary).HasMaxLength(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<UserEntity>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id).HasName("pk-user");
|
|
||||||
entity.Property(e => e.Email).HasMaxLength(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<ApiRefreshTokenEntity>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id).HasName("pk-api-refresh-token");
|
|
||||||
entity.HasIndex(e => e.TokenHash).IsUnique().HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
entity.HasIndex(e => e.UserId).HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<ManagedLibraryRoot>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id).HasName("pk-managed-library-root");
|
|
||||||
entity.HasIndex(e => e.Path).IsUnique().HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
entity.Property(e => e.Path).HasMaxLength(1024);
|
|
||||||
entity.Property(e => e.DisplayName).HasMaxLength(200);
|
|
||||||
entity.Property(e => e.LastScanError).HasMaxLength(2000);
|
|
||||||
entity.Property(e => e.IsAvailable).HasDefaultValue(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<ManagedFileRecord>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id).HasName("pk-managed-file-record");
|
|
||||||
entity.HasIndex(e => e.LibraryRootId).HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
entity.HasIndex(e => e.ThumbnailId).HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
entity.HasIndex(e => e.AbsolutePath).IsUnique().HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
entity.HasIndex(e => new { e.MediaType, e.Exists }).HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
entity.HasIndex(e => e.LastPlayedAt).HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
entity.HasIndex(e => e.FileCreationTimeUtc).HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
entity.Property(e => e.FileName).HasMaxLength(260);
|
|
||||||
entity.Property(e => e.RelativePath).HasMaxLength(1024);
|
|
||||||
entity.Property(e => e.AbsolutePath).HasMaxLength(2048);
|
|
||||||
entity.Property(e => e.Extension).HasMaxLength(32);
|
|
||||||
entity.Property(e => e.MediaType).HasMaxLength(20);
|
|
||||||
entity.Property(e => e.ContentType).HasMaxLength(100);
|
|
||||||
entity.HasOne(e => e.LibraryRoot)
|
|
||||||
.WithMany(e => e.Files)
|
|
||||||
.HasForeignKey(e => e.LibraryRootId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
entity.HasOne(e => e.Thumbnail)
|
|
||||||
.WithMany(e => e.Files)
|
|
||||||
.HasForeignKey(e => e.ThumbnailId)
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<ManagedThumbnailMap>(entity =>
|
|
||||||
{
|
|
||||||
entity.HasKey(e => e.Id).HasName("pk-managed-thumbnail-map");
|
|
||||||
entity.HasIndex(e => e.LibraryRootId).HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
entity.HasIndex(e => e.RelativePath).IsUnique().HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
entity.Property(e => e.RelativePath).HasMaxLength(1024);
|
|
||||||
entity.Property(e => e.ContentType).HasMaxLength(100);
|
|
||||||
entity.HasOne(e => e.LibraryRoot)
|
|
||||||
.WithMany(e => e.Thumbnails)
|
|
||||||
.HasForeignKey(e => e.LibraryRootId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,120 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Design;
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 设计时 DbContext 工厂,用于 EF Core 迁移工具生成迁移代码。
|
|
||||||
/// </summary>
|
|
||||||
public class AppDataContextFactory : IDesignTimeDbContextFactory<AppDataContext>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建用于设计时的 AppDataContext 实例,默认使用 SQLite 提供程序。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">命令行参数。</param>
|
|
||||||
/// <returns>配置好的数据上下文实例。</returns>
|
|
||||||
public AppDataContext CreateDbContext(string[] args)
|
|
||||||
{
|
|
||||||
return new AppDataContext(DesignTimeDatabaseConfiguration.Create(args));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQLite 迁移设计时工厂。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SqliteAppDataContextFactory : IDesignTimeDbContextFactory<SqliteAppDataContext>
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public SqliteAppDataContext CreateDbContext(string[] args)
|
|
||||||
=> new(DesignTimeDatabaseConfiguration.Create(args, DatabaseProvider.SQLite));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQL Server 迁移设计时工厂。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SqlServerAppDataContextFactory : IDesignTimeDbContextFactory<SqlServerAppDataContext>
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public SqlServerAppDataContext CreateDbContext(string[] args)
|
|
||||||
=> new(DesignTimeDatabaseConfiguration.Create(args, DatabaseProvider.SqlServer));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PostgreSQL 迁移设计时工厂。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class PostgreSqlAppDataContextFactory : IDesignTimeDbContextFactory<PostgreSqlAppDataContext>
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public PostgreSqlAppDataContext CreateDbContext(string[] args)
|
|
||||||
=> new(DesignTimeDatabaseConfiguration.Create(args, DatabaseProvider.PostgreSQL));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// MySQL 迁移设计时工厂。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class MySqlAppDataContextFactory : IDesignTimeDbContextFactory<MySqlAppDataContext>
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public MySqlAppDataContext CreateDbContext(string[] args)
|
|
||||||
=> new(DesignTimeDatabaseConfiguration.Create(args, DatabaseProvider.MySQL));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 为设计时工具(dotnet ef migrations)提供数据库连接配置。
|
|
||||||
/// </summary>
|
|
||||||
internal static class DesignTimeDatabaseConfiguration
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 解析命令行参数中的 --provider 选项,创建对应的 <see cref="DatabaseConfiguration"/>。
|
|
||||||
/// 未指定提供程序时默认使用 SQLite。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">命令行参数。</param>
|
|
||||||
/// <param name="defaultProvider">未指定时的默认数据库提供程序。</param>
|
|
||||||
/// <returns>对应数据库提供程序的配置。</returns>
|
|
||||||
public static DatabaseConfiguration Create(string[] args, DatabaseProvider defaultProvider = DatabaseProvider.SQLite)
|
|
||||||
{
|
|
||||||
DatabaseProviderRegistry.RegisterDefaults();
|
|
||||||
|
|
||||||
var provider = GetProvider(args) ?? defaultProvider;
|
|
||||||
return provider switch
|
|
||||||
{
|
|
||||||
DatabaseProvider.SQLite => DatabaseConfiguration.ForSQLite("fileshare-api.db"),
|
|
||||||
DatabaseProvider.SqlServer => DatabaseConfiguration.ForSqlServer("(localdb)\\MSSQLLocalDB", "FileShareApi"),
|
|
||||||
DatabaseProvider.PostgreSQL => DatabaseConfiguration.ForPostgreSQL("localhost", "fileshare_api", "postgres", "postgres"),
|
|
||||||
DatabaseProvider.MySQL => DatabaseConfiguration.ForMySQL("localhost", "fileshare_api", "root", "root"),
|
|
||||||
_ => DatabaseConfiguration.ForSQLite("fileshare-api.db"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从命令行参数中解析 --provider 选项的值。
|
|
||||||
/// 支持 <c>--provider sqlite</c> 和 <c>--provider=sqlite</c> 两种格式。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">命令行参数。</param>
|
|
||||||
/// <returns>解析到的数据库提供程序,未指定或无法识别时返回 null。</returns>
|
|
||||||
private static DatabaseProvider? GetProvider(string[] args)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
var arg = args[i];
|
|
||||||
string? value = null;
|
|
||||||
|
|
||||||
if (arg.Equals("--provider", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
|
|
||||||
{
|
|
||||||
value = args[i + 1];
|
|
||||||
}
|
|
||||||
else if (arg.StartsWith("--provider=", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
value = arg["--provider=".Length..];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(value)
|
|
||||||
&& Enum.TryParse<DatabaseProvider>(value, ignoreCase: true, out var provider))
|
|
||||||
{
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 应用数据库上下文基类 —— 自动根据 DatabaseConfiguration 选择数据库提供程序。
|
|
||||||
/// 所有业务 DbContext 继承此类即可获得多数据库支持。
|
|
||||||
/// </summary>
|
|
||||||
public abstract class AppDbContext(DatabaseConfiguration dbConfig) : DbContext
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库配置。
|
|
||||||
/// </summary>
|
|
||||||
private readonly DatabaseConfiguration _dbConfig = dbConfig;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 配置数据库提供程序和连接选项。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="optionsBuilder">选项构建器。</param>
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
||||||
{
|
|
||||||
if (optionsBuilder.IsConfigured) return;
|
|
||||||
|
|
||||||
ConfigureProvider(optionsBuilder, _dbConfig);
|
|
||||||
|
|
||||||
if (_dbConfig.EnableDetailedLog)
|
|
||||||
{
|
|
||||||
optionsBuilder.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启用详细的 EF Core 错误信息
|
|
||||||
optionsBuilder.EnableDetailedErrors();
|
|
||||||
optionsBuilder.EnableSensitiveDataLogging(_dbConfig.EnableDetailedLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据配置选择数据库提供程序。
|
|
||||||
/// 使用注册模式,由宿主项目注册具体的提供程序实现。
|
|
||||||
/// </summary>
|
|
||||||
public static void ConfigureProvider(DbContextOptionsBuilder optionsBuilder, DatabaseConfiguration config)
|
|
||||||
{
|
|
||||||
if (DatabaseProviderRegistry.TryGet(config.Provider, out var configurator))
|
|
||||||
{
|
|
||||||
configurator(optionsBuilder, config.ConnectionString, config.Timeout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotSupportedException(
|
|
||||||
$"数据库提供程序 {config.Provider} 未注册。" +
|
|
||||||
$"请在宿主项目中安装对应的 EF Core NuGet 包并调用 DatabaseProviderRegistry.Register()。");
|
|
||||||
}
|
|
||||||
|
|
||||||
optionsBuilder.EnableDetailedErrors();
|
|
||||||
optionsBuilder.EnableSensitiveDataLogging(config.EnableDetailedLog);
|
|
||||||
|
|
||||||
if (config.EnableDetailedLog)
|
|
||||||
{
|
|
||||||
optionsBuilder.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 保存时自动设置时间戳。
|
|
||||||
/// </summary>
|
|
||||||
public override int SaveChanges(bool acceptAllChangesOnSuccess)
|
|
||||||
{
|
|
||||||
SetTimestamps();
|
|
||||||
return base.SaveChanges(acceptAllChangesOnSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 异步保存更改,自动设置时间戳。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="acceptAllChangesOnSuccess">是否在成功时接受所有更改。</param>
|
|
||||||
/// <param name="cancellationToken">取消令牌。</param>
|
|
||||||
/// <returns>受影响的行数。</returns>
|
|
||||||
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
SetTimestamps();
|
|
||||||
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 自动设置新增或修改实体的 CreatedAt 和 UpdatedAt 时间戳。
|
|
||||||
/// </summary>
|
|
||||||
private void SetTimestamps()
|
|
||||||
{
|
|
||||||
var entries = ChangeTracker.Entries()
|
|
||||||
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);
|
|
||||||
|
|
||||||
foreach (var entry in entries)
|
|
||||||
{
|
|
||||||
var entity = entry.Entity;
|
|
||||||
|
|
||||||
// 使用反射设置 CreatedAt / UpdatedAt(如果存在)
|
|
||||||
var createdAtProp = entity.GetType().GetProperty("CreatedAt");
|
|
||||||
var updatedAtProp = entity.GetType().GetProperty("UpdatedAt");
|
|
||||||
|
|
||||||
if (entry.State == EntityState.Added && createdAtProp != null)
|
|
||||||
{
|
|
||||||
createdAtProp.SetValue(entity, DateTime.UtcNow);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatedAtProp != null)
|
|
||||||
{
|
|
||||||
updatedAtProp.SetValue(entity, DateTime.UtcNow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 支持的数据库提供程序类型。
|
|
||||||
/// </summary>
|
|
||||||
public enum DatabaseProvider
|
|
||||||
{
|
|
||||||
/// <summary>SQLite(本地文件数据库,无需安装,跨平台)</summary>
|
|
||||||
SQLite,
|
|
||||||
|
|
||||||
/// <summary>MySQL / MariaDB</summary>
|
|
||||||
MySQL,
|
|
||||||
|
|
||||||
/// <summary>PostgreSQL</summary>
|
|
||||||
PostgreSQL,
|
|
||||||
|
|
||||||
/// <summary>SQL Server</summary>
|
|
||||||
SqlServer
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库连接配置 —— 在 appsettings.json 中配置。
|
|
||||||
/// </summary>
|
|
||||||
public class DatabaseConfiguration
|
|
||||||
{
|
|
||||||
/// <summary>数据库提供程序</summary>
|
|
||||||
public DatabaseProvider Provider { get; set; } = DatabaseProvider.SQLite;
|
|
||||||
|
|
||||||
/// <summary>连接字符串</summary>
|
|
||||||
public string ConnectionString { get; set; } = "Data Source=app.db";
|
|
||||||
|
|
||||||
/// <summary>是否在启动时自动执行迁移</summary>
|
|
||||||
public bool AutoMigrate { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否在迁移前删除并重建当前连接指向的数据库。
|
|
||||||
/// 仅用于切换数据库类型或本地开发重建库;生产环境默认必须保持 false。
|
|
||||||
/// </summary>
|
|
||||||
public bool RecreateDatabase { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>是否启用详细日志(会打印 SQL 语句)</summary>
|
|
||||||
public bool EnableDetailedLog { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>连接超时(秒)</summary>
|
|
||||||
public int Timeout { get; set; } = 30;
|
|
||||||
|
|
||||||
// ---- 快捷构建方法 ----
|
|
||||||
|
|
||||||
/// <summary>SQLite 本地数据库</summary>
|
|
||||||
public static DatabaseConfiguration ForSQLite(string dataSource = "app.db")
|
|
||||||
{
|
|
||||||
return new DatabaseConfiguration
|
|
||||||
{
|
|
||||||
Provider = DatabaseProvider.SQLite,
|
|
||||||
ConnectionString = $"Data Source={dataSource}",
|
|
||||||
AutoMigrate = true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>MySQL 数据库</summary>
|
|
||||||
public static DatabaseConfiguration ForMySQL(string server, string database, string user, string password, uint port = 3306)
|
|
||||||
{
|
|
||||||
return new DatabaseConfiguration
|
|
||||||
{
|
|
||||||
Provider = DatabaseProvider.MySQL,
|
|
||||||
ConnectionString = $"Server={server};Port={port};Database={database};User={user};Password={password};",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>PostgreSQL 数据库</summary>
|
|
||||||
public static DatabaseConfiguration ForPostgreSQL(string host, string database, string username, string password, int port = 5432)
|
|
||||||
{
|
|
||||||
return new DatabaseConfiguration
|
|
||||||
{
|
|
||||||
Provider = DatabaseProvider.PostgreSQL,
|
|
||||||
ConnectionString = $"Host={host};Port={port};Database={database};Username={username};Password={password};",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>SQL Server 数据库</summary>
|
|
||||||
public static DatabaseConfiguration ForSqlServer(string server, string database, string? user = null, string? password = null)
|
|
||||||
{
|
|
||||||
var connStr = string.IsNullOrEmpty(user)
|
|
||||||
? $"Server={server};Database={database};Trusted_Connection=True;TrustServerCertificate=True;"
|
|
||||||
: $"Server={server};Database={database};User Id={user};Password={password};TrustServerCertificate=True;";
|
|
||||||
return new DatabaseConfiguration
|
|
||||||
{
|
|
||||||
Provider = DatabaseProvider.SqlServer,
|
|
||||||
ConnectionString = connStr,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库服务注册扩展 —— 在 Program.cs 中一行配置数据库。
|
|
||||||
/// </summary>
|
|
||||||
public static class DatabaseExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 注册数据库上下文及相关服务。
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TContext">继承自 AppDbContext 的业务 DbContext</typeparam>
|
|
||||||
public static IServiceCollection AddAppDatabase<TContext>(
|
|
||||||
this IServiceCollection services,
|
|
||||||
DatabaseConfiguration config)
|
|
||||||
where TContext : AppDbContext
|
|
||||||
{
|
|
||||||
// 注册配置
|
|
||||||
services.AddSingleton(config);
|
|
||||||
|
|
||||||
if (typeof(TContext) == typeof(AppDataContext))
|
|
||||||
{
|
|
||||||
services.AddProviderAppDataContext(config);
|
|
||||||
services.AddScoped<DatabaseManager<TContext>>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册 DbContext
|
|
||||||
services.AddDbContext<TContext>(options =>
|
|
||||||
{
|
|
||||||
AppDbContext.ConfigureProvider(options, config);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 注册数据库管理器
|
|
||||||
services.AddScoped<DatabaseManager<TContext>>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据 <see cref="DatabaseConfiguration.Provider"/> 注册对应具体类型的 <see cref="AppDataContext"/> 实现。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="services">服务集合。</param>
|
|
||||||
/// <param name="config">数据库配置。</param>
|
|
||||||
/// <exception cref="NotSupportedException">数据库提供程序未注册时抛出。</exception>
|
|
||||||
private static void AddProviderAppDataContext(this IServiceCollection services, DatabaseConfiguration config)
|
|
||||||
{
|
|
||||||
switch (config.Provider)
|
|
||||||
{
|
|
||||||
case DatabaseProvider.SQLite:
|
|
||||||
services.AddDbContext<AppDataContext, SqliteAppDataContext>(options =>
|
|
||||||
AppDbContext.ConfigureProvider(options, config));
|
|
||||||
break;
|
|
||||||
case DatabaseProvider.SqlServer:
|
|
||||||
services.AddDbContext<AppDataContext, SqlServerAppDataContext>(options =>
|
|
||||||
AppDbContext.ConfigureProvider(options, config));
|
|
||||||
break;
|
|
||||||
case DatabaseProvider.PostgreSQL:
|
|
||||||
services.AddDbContext<AppDataContext, PostgreSqlAppDataContext>(options =>
|
|
||||||
AppDbContext.ConfigureProvider(options, config));
|
|
||||||
break;
|
|
||||||
case DatabaseProvider.MySQL:
|
|
||||||
services.AddDbContext<AppDataContext, MySqlAppDataContext>(options =>
|
|
||||||
AppDbContext.ConfigureProvider(options, config));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException($"数据库提供程序 {config.Provider} 未注册。");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化数据库(在应用启动时调用一次)。
|
|
||||||
/// </summary>
|
|
||||||
public static IServiceProvider InitializeDatabase<TContext>(
|
|
||||||
this IServiceProvider serviceProvider,
|
|
||||||
Action<TContext, IServiceProvider?>? seeder = null)
|
|
||||||
where TContext : AppDbContext
|
|
||||||
{
|
|
||||||
using var scope = serviceProvider.CreateScope();
|
|
||||||
var dbManager = scope.ServiceProvider.GetRequiredService<DatabaseManager<TContext>>();
|
|
||||||
|
|
||||||
// 同步等待初始化(启动时阻塞)
|
|
||||||
dbManager.InitializeAsync(seeder).GetAwaiter().GetResult();
|
|
||||||
|
|
||||||
return serviceProvider;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,225 +0,0 @@
|
|||||||
using FileShare_Common.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库管理器 —— 负责连接测试、自动迁移、种子数据、版本检查。
|
|
||||||
/// 在应用启动时调用,确保数据库结构与应用代码同步。
|
|
||||||
/// </summary>
|
|
||||||
public class DatabaseManager<TContext> where TContext : AppDbContext
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库上下文实例。
|
|
||||||
/// </summary>
|
|
||||||
private readonly TContext _context;
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库配置。
|
|
||||||
/// </summary>
|
|
||||||
private readonly DatabaseConfiguration _config;
|
|
||||||
/// <summary>
|
|
||||||
/// DI 服务提供程序(可选,用于种子数据中解析服务)。
|
|
||||||
/// </summary>
|
|
||||||
private readonly IServiceProvider? _serviceProvider;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化数据库管理器。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">数据库上下文。</param>
|
|
||||||
/// <param name="config">数据库配置。</param>
|
|
||||||
/// <param name="serviceProvider">可选的 DI 容器。</param>
|
|
||||||
public DatabaseManager(TContext context, DatabaseConfiguration config, IServiceProvider? serviceProvider = null)
|
|
||||||
{
|
|
||||||
_context = context;
|
|
||||||
_config = config;
|
|
||||||
_serviceProvider = serviceProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化数据库:测试连接 → 自动迁移 → 种子数据。
|
|
||||||
/// </summary>
|
|
||||||
public async Task InitializeAsync(Action<TContext, IServiceProvider?>? seeder = null)
|
|
||||||
{
|
|
||||||
AppLog.Information(
|
|
||||||
"正在初始化数据库 Provider={Provider}, AppVersion={AppVersion}",
|
|
||||||
_config.Provider,
|
|
||||||
GetApplicationVersion());
|
|
||||||
|
|
||||||
// 1. 自动迁移(如果启用)。MigrateAsync 会按迁移历史顺序执行全部待处理迁移,
|
|
||||||
// 支持用户从较旧软件版本直接升级到当前版本。
|
|
||||||
if (_config.AutoMigrate)
|
|
||||||
{
|
|
||||||
if (_config.RecreateDatabase)
|
|
||||||
{
|
|
||||||
AppLog.Warning(
|
|
||||||
"RecreateDatabase=true,将删除并重建当前连接指向的数据库。Provider={Provider}",
|
|
||||||
_config.Provider);
|
|
||||||
|
|
||||||
await _context.Database.EnsureDeletedAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
await MigrateAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var canConnect = await CanConnectAsync();
|
|
||||||
if (!canConnect)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
$"无法连接到数据库 [{_config.Provider}],请检查连接字符串和数据库服务状态。");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 种子数据
|
|
||||||
if (seeder != null)
|
|
||||||
{
|
|
||||||
seeder(_context, _serviceProvider);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 测试数据库连接是否正常。
|
|
||||||
/// </summary>
|
|
||||||
public async Task<bool> CanConnectAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await _context.Database.CanConnectAsync();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
AppLog.Warning("数据库连接测试失败 Provider={Provider} Error={Error}", _config.Provider, ex.Message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 执行待处理的迁移。
|
|
||||||
/// 使用 EF Core 原生迁移机制,自动检测并应用 Schema 变更。
|
|
||||||
/// </summary>
|
|
||||||
public async Task MigrateAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var appliedMigrations = (await _context.Database.GetAppliedMigrationsAsync()).ToList();
|
|
||||||
var pendingMigrations = await _context.Database.GetPendingMigrationsAsync();
|
|
||||||
|
|
||||||
if (pendingMigrations.Any())
|
|
||||||
{
|
|
||||||
if (appliedMigrations.Count == 0)
|
|
||||||
{
|
|
||||||
AppLog.Information(
|
|
||||||
"未检测到已应用迁移,将按当前 Provider={Provider} 从 0 构建完整表结构",
|
|
||||||
_config.Provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppLog.Information(
|
|
||||||
"当前已应用 {AppliedCount} 个迁移,检测到 {PendingCount} 个待执行迁移: {Migrations}",
|
|
||||||
appliedMigrations.Count,
|
|
||||||
pendingMigrations.Count(),
|
|
||||||
string.Join(", ", pendingMigrations));
|
|
||||||
|
|
||||||
await _context.Database.MigrateAsync();
|
|
||||||
|
|
||||||
AppLog.Information("数据库迁移完成({Count} 个迁移已应用)", pendingMigrations.Count());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AppLog.Information("数据库已是最新版本,无需迁移");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
AppLog.Error(ex, "数据库迁移失败");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取当前应用程序的版本号,优先读取 AssemblyInformationalVersion,回退到 AssemblyVersion。
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>应用程序版本字符串。</returns>
|
|
||||||
private static string GetApplicationVersion()
|
|
||||||
{
|
|
||||||
var assembly = Assembly.GetEntryAssembly() ?? typeof(TContext).Assembly;
|
|
||||||
return assembly
|
|
||||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
|
|
||||||
?.InformationalVersion
|
|
||||||
?? assembly.GetName().Version?.ToString()
|
|
||||||
?? "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取数据库当前版本信息。
|
|
||||||
/// </summary>
|
|
||||||
public async Task<DatabaseVersionInfo> GetVersionInfoAsync()
|
|
||||||
{
|
|
||||||
var appliedMigrations = await _context.Database.GetAppliedMigrationsAsync();
|
|
||||||
var pendingMigrations = await _context.Database.GetPendingMigrationsAsync();
|
|
||||||
|
|
||||||
return new DatabaseVersionInfo
|
|
||||||
{
|
|
||||||
Provider = _config.Provider.ToString(),
|
|
||||||
AppliedMigrations = appliedMigrations.ToList(),
|
|
||||||
PendingMigrations = pendingMigrations.ToList(),
|
|
||||||
IsLatest = !pendingMigrations.Any(),
|
|
||||||
CanConnect = await CanConnectAsync(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 生成从指定迁移到最新版本的 SQL 脚本(用于生产环境审计)。
|
|
||||||
/// </summary>
|
|
||||||
public string GenerateMigrationScript(string? fromMigration = null)
|
|
||||||
{
|
|
||||||
var migrator = _context.GetService<IMigrator>();
|
|
||||||
return fromMigration is null
|
|
||||||
? migrator.GenerateScript()
|
|
||||||
: migrator.GenerateScript(fromMigration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 确保数据库已创建(不执行迁移,适用于简单场景)。
|
|
||||||
/// </summary>
|
|
||||||
public bool EnsureCreated()
|
|
||||||
{
|
|
||||||
return _context.Database.EnsureCreated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库版本信息 DTO。
|
|
||||||
/// </summary>
|
|
||||||
public class DatabaseVersionInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置数据库提供程序名称。
|
|
||||||
/// </summary>
|
|
||||||
public string Provider { get; set; } = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置已应用的迁移列表。
|
|
||||||
/// </summary>
|
|
||||||
public List<string> AppliedMigrations { get; set; } = new();
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置待应用的迁移列表。
|
|
||||||
/// </summary>
|
|
||||||
public List<string> PendingMigrations { get; set; } = new();
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置是否为最新版本。
|
|
||||||
/// </summary>
|
|
||||||
public bool IsLatest { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 获取或设置数据库是否可连接。
|
|
||||||
/// </summary>
|
|
||||||
public bool CanConnect { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 数据库提供程序注册表 —— 统一注册所有支持的提供程序配置委托。
|
|
||||||
/// 具体使用哪个提供程序由各宿主项目决定:
|
|
||||||
/// FileShare-API:从 appsettings.json 的 DatabaseConfiguration 节读取;
|
|
||||||
/// FileShare-PC :固定使用 SQLite。
|
|
||||||
/// </summary>
|
|
||||||
public static class DatabaseProviderRegistry
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 提供程序配置委托:optionsBuilder, connectionString, timeout → void
|
|
||||||
/// </summary>
|
|
||||||
public delegate void ProviderConfigurator(DbContextOptionsBuilder optionsBuilder, string connectionString, int timeout);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 保存已注册的数据库提供程序及其配置委托。
|
|
||||||
/// </summary>
|
|
||||||
private static readonly Dictionary<DatabaseProvider, ProviderConfigurator> _providers = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注册一个数据库提供程序。
|
|
||||||
/// </summary>
|
|
||||||
public static void Register(DatabaseProvider provider, ProviderConfigurator configurator)
|
|
||||||
{
|
|
||||||
_providers[provider] = configurator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 尝试获取注册的提供程序配置。
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryGet(DatabaseProvider provider, out ProviderConfigurator configurator)
|
|
||||||
{
|
|
||||||
return _providers.TryGetValue(provider, out configurator!);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注册所有内置提供程序的默认配置(四个包均已内置在 FileShare-EFCore 中)。
|
|
||||||
/// 注册完成后由调用方根据自身需求选择具体的 <see cref="DatabaseProvider"/>。
|
|
||||||
/// </summary>
|
|
||||||
public static void RegisterDefaults()
|
|
||||||
{
|
|
||||||
Register(DatabaseProvider.SQLite, (opts, cs, timeout) =>
|
|
||||||
opts.UseSqlite(cs, o => o.CommandTimeout(timeout)));
|
|
||||||
|
|
||||||
Register(DatabaseProvider.SqlServer, (opts, cs, timeout) =>
|
|
||||||
opts.UseSqlServer(cs, o => { o.CommandTimeout(timeout); o.EnableRetryOnFailure(3); }));
|
|
||||||
|
|
||||||
Register(DatabaseProvider.PostgreSQL, (opts, cs, timeout) =>
|
|
||||||
opts.UseNpgsql(cs, o => { o.CommandTimeout(timeout); o.EnableRetryOnFailure(3); }));
|
|
||||||
|
|
||||||
Register(DatabaseProvider.MySQL, (opts, cs, timeout) =>
|
|
||||||
opts.UseMySQL(cs, o => o.CommandTimeout(timeout)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
namespace FileShare_EFCore.Database
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// SQLite 专用 DbContext,用于隔离 SQLite 迁移集。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SqliteAppDataContext(DatabaseConfiguration dbConfig) : AppDataContext(dbConfig)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// SQL Server 专用 DbContext,用于隔离 SQL Server 迁移集。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SqlServerAppDataContext(DatabaseConfiguration dbConfig) : AppDataContext(dbConfig)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PostgreSQL 专用 DbContext,用于隔离 PostgreSQL 迁移集。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class PostgreSqlAppDataContext(DatabaseConfiguration dbConfig) : AppDataContext(dbConfig)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// MySQL 专用 DbContext,用于隔离 MySQL 迁移集。
|
|
||||||
/// </summary>
|
|
||||||
public sealed class MySqlAppDataContext(DatabaseConfiguration dbConfig) : AppDataContext(dbConfig)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
|
||||||
<RootNamespace>FileShare_EFCore</RootNamespace>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.7" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.7" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
|
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
|
||||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="10.0.7" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.7" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\FileShare-Common\FileShare-Common.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@ -1,175 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(MySqlAppDataContext))]
|
|
||||||
[Migration("20260520082626_AutoMigration_20260520162543")]
|
|
||||||
partial class AutoMigration_20260520162543
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("varchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("varchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using MySql.EntityFrameworkCore.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260520162543 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AlterDatabase()
|
|
||||||
.Annotation("MySQL:Charset", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "api-refresh-token",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<long>(type: "bigint", nullable: false)
|
|
||||||
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
|
|
||||||
userid = table.Column<int>(name: "user-id", type: "int", nullable: false),
|
|
||||||
tokenhash = table.Column<string>(name: "token-hash", type: "varchar(128)", maxLength: 128, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime(6)", nullable: false),
|
|
||||||
expiresat = table.Column<DateTime>(name: "expires-at", type: "datetime(6)", nullable: false),
|
|
||||||
revokedat = table.Column<DateTime>(name: "revoked-at", type: "datetime(6)", nullable: true),
|
|
||||||
replacedbytokenhash = table.Column<string>(name: "replaced-by-token-hash", type: "varchar(128)", maxLength: 128, nullable: true),
|
|
||||||
device = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true),
|
|
||||||
ipaddress = table.Column<string>(name: "ip-address", type: "varchar(64)", maxLength: 64, nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-api-refresh-token", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "API refresh token")
|
|
||||||
.Annotation("MySQL:Charset", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "user",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false, comment: "用户主键")
|
|
||||||
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
|
|
||||||
name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true, comment: "用户名称"),
|
|
||||||
email = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true, comment: "用户邮箱"),
|
|
||||||
phonenumber = table.Column<string>(name: "phone-number", type: "varchar(50)", maxLength: 50, nullable: true, comment: "电话号码"),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime(6)", nullable: false, comment: "创建时间"),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime(6)", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-user", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "用户实体,演示数据库 CRUD 操作")
|
|
||||||
.Annotation("MySQL:Charset", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "weather-forecast",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false, comment: "天气预报主键")
|
|
||||||
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
|
|
||||||
date = table.Column<DateOnly>(type: "date", nullable: false, comment: "预报日期"),
|
|
||||||
temperaturec = table.Column<int>(name: "temperature-c", type: "int", nullable: false, comment: "摄氏温度"),
|
|
||||||
summary = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true, comment: "天气摘要"),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime(6)", nullable: false, comment: "创建时间"),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime(6)", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-weather-forecast", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "天气预报数据实体")
|
|
||||||
.Annotation("MySQL:Charset", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-hash",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "token-hash",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-user-id",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "user-id");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "api-refresh-token");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "user");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "weather-forecast");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,181 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(MySqlAppDataContext))]
|
|
||||||
[Migration("20260520083306_AutoMigration_20260520163216")]
|
|
||||||
partial class AutoMigration_20260520163216
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("varchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("varchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260520163216 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user",
|
|
||||||
type: "varchar(200)",
|
|
||||||
maxLength: 200,
|
|
||||||
nullable: true,
|
|
||||||
comment: "密码哈希值");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,370 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(MySqlAppDataContext))]
|
|
||||||
[Migration("20260522082856_AutoMigration_20260522162758")]
|
|
||||||
partial class AutoMigration_20260522162758
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("varchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("varchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("varchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("varchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("varchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<string>("ThumbnailPath")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("varchar(512)")
|
|
||||||
.HasColumnName("thumbnail-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("varchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("varchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,113 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using MySql.EntityFrameworkCore.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260522162758 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-library-root",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
|
|
||||||
path = table.Column<string>(type: "varchar(1024)", maxLength: 1024, nullable: false),
|
|
||||||
displayname = table.Column<string>(name: "display-name", type: "varchar(200)", maxLength: 200, nullable: false),
|
|
||||||
isenabled = table.Column<bool>(name: "is-enabled", type: "tinyint(1)", nullable: false),
|
|
||||||
isavailable = table.Column<bool>(name: "is-available", type: "tinyint(1)", nullable: false, defaultValue: true),
|
|
||||||
scanintervalminutes = table.Column<int>(name: "scan-interval-minutes", type: "int", nullable: false),
|
|
||||||
lastscanstartedat = table.Column<DateTime>(name: "last-scan-started-at", type: "datetime(6)", nullable: true),
|
|
||||||
lastscancompletedat = table.Column<DateTime>(name: "last-scan-completed-at", type: "datetime(6)", nullable: true),
|
|
||||||
lastscanerror = table.Column<string>(name: "last-scan-error", type: "varchar(2000)", maxLength: 2000, nullable: true),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime(6)", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime(6)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-library-root", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "文件库根目录")
|
|
||||||
.Annotation("MySQL:Charset", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-file-record",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "int", nullable: false),
|
|
||||||
filename = table.Column<string>(name: "file-name", type: "varchar(260)", maxLength: 260, nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "varchar(1024)", maxLength: 1024, nullable: false),
|
|
||||||
absolutepath = table.Column<string>(name: "absolute-path", type: "varchar(2048)", maxLength: 2048, nullable: false),
|
|
||||||
extension = table.Column<string>(type: "varchar(32)", maxLength: 32, nullable: false),
|
|
||||||
sizebytes = table.Column<long>(name: "size-bytes", type: "bigint", nullable: false),
|
|
||||||
lastwritetimeutc = table.Column<DateTime>(name: "last-write-time-utc", type: "datetime(6)", nullable: false),
|
|
||||||
mediatype = table.Column<string>(name: "media-type", type: "varchar(20)", maxLength: 20, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "varchar(100)", maxLength: 100, nullable: false),
|
|
||||||
exists = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
|
||||||
lastseenat = table.Column<DateTime>(name: "last-seen-at", type: "datetime(6)", nullable: false),
|
|
||||||
thumbnailpath = table.Column<string>(name: "thumbnail-path", type: "varchar(512)", maxLength: 512, nullable: true),
|
|
||||||
videoduration = table.Column<double>(name: "video-duration", type: "double", nullable: true),
|
|
||||||
lastplayedat = table.Column<DateTime>(name: "last-played-at", type: "datetime(6)", nullable: true),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime(6)", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime(6)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-file-record", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件库文件记录")
|
|
||||||
.Annotation("MySQL:Charset", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-absolute-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "absolute-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-last-played-at",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "last-played-at");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-media-type-exists",
|
|
||||||
table: "managed-file-record",
|
|
||||||
columns: new[] { "media-type", "exists" });
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-root-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-library-root-path",
|
|
||||||
table: "managed-library-root",
|
|
||||||
column: "path",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-library-root");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,444 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(MySqlAppDataContext))]
|
|
||||||
[Migration("20260522084325_AddThumbnailMap")]
|
|
||||||
partial class AddThumbnailMap
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("varchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("varchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("varchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("varchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("varchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("varchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("varchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using MySql.EntityFrameworkCore.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddThumbnailMap : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "int",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-thumbnail-map",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "int", nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "varchar(1024)", maxLength: 1024, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "varchar(100)", maxLength: 100, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime(6)", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime(6)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-thumbnail-map", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-thumbnail-map_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件缩略图映射记录")
|
|
||||||
.Annotation("MySQL:Charset", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-relative-path",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "relative-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-root-id",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id",
|
|
||||||
principalTable: "managed-thumbnail-map",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.SetNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-thumbnail-map");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "varchar(512)",
|
|
||||||
maxLength: 512,
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,448 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(MySqlAppDataContext))]
|
|
||||||
[Migration("20260522092342_AddPlaybackPosition")]
|
|
||||||
partial class AddPlaybackPosition
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("varchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("varchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("varchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("varchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("varchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("varchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("varchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddPlaybackPosition : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<double>(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "double",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,455 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(MySqlAppDataContext))]
|
|
||||||
[Migration("20260523023700_AutoMigration_20260523103531")]
|
|
||||||
partial class AutoMigration_20260523103531
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("varchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("varchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("varchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("FileCreationTimeUtc")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("file-creation-time-utc");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("varchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("varchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("FileCreationTimeUtc")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("varchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("varchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260523103531 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "datetime(6)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "file-creation-time-utc");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,452 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.MySQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(MySqlAppDataContext))]
|
|
||||||
partial class MySqlAppDataContextModelSnapshot : ModelSnapshot
|
|
||||||
{
|
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("varchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("varchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("varchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("varchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("FileCreationTimeUtc")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("file-creation-time-utc");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("varchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("varchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("FileCreationTimeUtc")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("tinyint(1)")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("varchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("varchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("varchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("varchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("varchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime(6)")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,184 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PostgreSqlAppDataContext))]
|
|
||||||
[Migration("20260520082617_AutoMigration_20260520162543")]
|
|
||||||
partial class AutoMigration_20260520162543
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("character varying(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260520162543 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "api-refresh-token",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<long>(type: "bigint", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
userid = table.Column<int>(name: "user-id", type: "integer", nullable: false),
|
|
||||||
tokenhash = table.Column<string>(name: "token-hash", type: "character varying(128)", maxLength: 128, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "timestamp with time zone", nullable: false),
|
|
||||||
expiresat = table.Column<DateTime>(name: "expires-at", type: "timestamp with time zone", nullable: false),
|
|
||||||
revokedat = table.Column<DateTime>(name: "revoked-at", type: "timestamp with time zone", nullable: true),
|
|
||||||
replacedbytokenhash = table.Column<string>(name: "replaced-by-token-hash", type: "character varying(128)", maxLength: 128, nullable: true),
|
|
||||||
device = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
|
||||||
ipaddress = table.Column<string>(name: "ip-address", type: "character varying(64)", maxLength: 64, nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-api-refresh-token", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "API refresh token");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "user",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false, comment: "用户主键")
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true, comment: "用户名称"),
|
|
||||||
email = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true, comment: "用户邮箱"),
|
|
||||||
phonenumber = table.Column<string>(name: "phone-number", type: "character varying(50)", maxLength: 50, nullable: true, comment: "电话号码"),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "timestamp with time zone", nullable: false, comment: "创建时间"),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "timestamp with time zone", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-user", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "用户实体,演示数据库 CRUD 操作");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "weather-forecast",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false, comment: "天气预报主键")
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
date = table.Column<DateOnly>(type: "date", nullable: false, comment: "预报日期"),
|
|
||||||
temperaturec = table.Column<int>(name: "temperature-c", type: "integer", nullable: false, comment: "摄氏温度"),
|
|
||||||
summary = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true, comment: "天气摘要"),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "timestamp with time zone", nullable: false, comment: "创建时间"),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "timestamp with time zone", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-weather-forecast", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "天气预报数据实体");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-hash",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "token-hash",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-user-id",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "user-id");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "api-refresh-token");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "user");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "weather-forecast");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,190 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PostgreSqlAppDataContext))]
|
|
||||||
[Migration("20260520083254_AutoMigration_20260520163216")]
|
|
||||||
partial class AutoMigration_20260520163216
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("character varying(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260520163216 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user",
|
|
||||||
type: "character varying(200)",
|
|
||||||
maxLength: 200,
|
|
||||||
nullable: true,
|
|
||||||
comment: "密码哈希值");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,383 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PostgreSqlAppDataContext))]
|
|
||||||
[Migration("20260522082843_AutoMigration_20260522162758")]
|
|
||||||
partial class AutoMigration_20260522162758
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("character varying(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("character varying(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("character varying(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("character varying(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<string>("ThumbnailPath")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("character varying(512)")
|
|
||||||
.HasColumnName("thumbnail-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("character varying(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,111 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260522162758 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-library-root",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
path = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
|
|
||||||
displayname = table.Column<string>(name: "display-name", type: "character varying(200)", maxLength: 200, nullable: false),
|
|
||||||
isenabled = table.Column<bool>(name: "is-enabled", type: "boolean", nullable: false),
|
|
||||||
isavailable = table.Column<bool>(name: "is-available", type: "boolean", nullable: false, defaultValue: true),
|
|
||||||
scanintervalminutes = table.Column<int>(name: "scan-interval-minutes", type: "integer", nullable: false),
|
|
||||||
lastscanstartedat = table.Column<DateTime>(name: "last-scan-started-at", type: "timestamp with time zone", nullable: true),
|
|
||||||
lastscancompletedat = table.Column<DateTime>(name: "last-scan-completed-at", type: "timestamp with time zone", nullable: true),
|
|
||||||
lastscanerror = table.Column<string>(name: "last-scan-error", type: "character varying(2000)", maxLength: 2000, nullable: true),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "timestamp with time zone", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "timestamp with time zone", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-library-root", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "文件库根目录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-file-record",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "integer", nullable: false),
|
|
||||||
filename = table.Column<string>(name: "file-name", type: "character varying(260)", maxLength: 260, nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "character varying(1024)", maxLength: 1024, nullable: false),
|
|
||||||
absolutepath = table.Column<string>(name: "absolute-path", type: "character varying(2048)", maxLength: 2048, nullable: false),
|
|
||||||
extension = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
|
||||||
sizebytes = table.Column<long>(name: "size-bytes", type: "bigint", nullable: false),
|
|
||||||
lastwritetimeutc = table.Column<DateTime>(name: "last-write-time-utc", type: "timestamp with time zone", nullable: false),
|
|
||||||
mediatype = table.Column<string>(name: "media-type", type: "character varying(20)", maxLength: 20, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "character varying(100)", maxLength: 100, nullable: false),
|
|
||||||
exists = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
lastseenat = table.Column<DateTime>(name: "last-seen-at", type: "timestamp with time zone", nullable: false),
|
|
||||||
thumbnailpath = table.Column<string>(name: "thumbnail-path", type: "character varying(512)", maxLength: 512, nullable: true),
|
|
||||||
videoduration = table.Column<double>(name: "video-duration", type: "double precision", nullable: true),
|
|
||||||
lastplayedat = table.Column<DateTime>(name: "last-played-at", type: "timestamp with time zone", nullable: true),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "timestamp with time zone", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "timestamp with time zone", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-file-record", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件库文件记录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-absolute-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "absolute-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-last-played-at",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "last-played-at");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-media-type-exists",
|
|
||||||
table: "managed-file-record",
|
|
||||||
columns: new[] { "media-type", "exists" });
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-root-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-library-root-path",
|
|
||||||
table: "managed-library-root",
|
|
||||||
column: "path",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-library-root");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,459 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PostgreSqlAppDataContext))]
|
|
||||||
[Migration("20260522084325_AddThumbnailMap")]
|
|
||||||
partial class AddThumbnailMap
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("character varying(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("character varying(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("character varying(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("character varying(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("character varying(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddThumbnailMap : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "integer",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-thumbnail-map",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "integer", nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "character varying(1024)", maxLength: 1024, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "character varying(100)", maxLength: 100, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "timestamp with time zone", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "timestamp with time zone", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-thumbnail-map", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-thumbnail-map_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件缩略图映射记录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-relative-path",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "relative-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-root-id",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id",
|
|
||||||
principalTable: "managed-thumbnail-map",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.SetNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-thumbnail-map");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "character varying(512)",
|
|
||||||
maxLength: 512,
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,463 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PostgreSqlAppDataContext))]
|
|
||||||
[Migration("20260522092330_AddPlaybackPosition")]
|
|
||||||
partial class AddPlaybackPosition
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("character varying(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("character varying(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("character varying(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("character varying(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("character varying(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddPlaybackPosition : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<double>(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "double precision",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,470 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PostgreSqlAppDataContext))]
|
|
||||||
[Migration("20260523023643_AutoMigration_20260523103531")]
|
|
||||||
partial class AutoMigration_20260523103531
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("character varying(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("character varying(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("character varying(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("FileCreationTimeUtc")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("file-creation-time-utc");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("character varying(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("FileCreationTimeUtc")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("character varying(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260523103531 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "timestamp with time zone",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "file-creation-time-utc");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,467 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.PostgreSQL
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PostgreSqlAppDataContext))]
|
|
||||||
partial class PostgreSqlAppDataContextModelSnapshot : ModelSnapshot
|
|
||||||
{
|
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("character varying(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("character varying(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("character varying(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("FileCreationTimeUtc")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("file-creation-time-utc");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("character varying(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("character varying(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("FileCreationTimeUtc")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("character varying(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("character varying(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("character varying(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("character varying(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("character varying(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260514000100_InitialCreate")]
|
|
||||||
partial class InitialCreate
|
|
||||||
{
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.0");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.HasComment("用户主键")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasComment("创建时间")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasComment("用户邮箱")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasMaxLength(200);
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasComment("用户名称")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasMaxLength(100);
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasComment("更新时间")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.HasComment("天气预报主键")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.ValueGeneratedOnAdd();
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasComment("创建时间")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasComment("预报日期")
|
|
||||||
.HasColumnName("date");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasComment("天气摘要")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasMaxLength(200);
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasComment("摄氏温度")
|
|
||||||
.HasColumnName("temperature-c");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasComment("更新时间")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 初始数据库基线。后续软件版本只追加新的 Migration,不修改已发布 Migration。
|
|
||||||
/// </summary>
|
|
||||||
public partial class InitialCreate : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "user",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(name: "id", nullable: false, comment: "用户主键")
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1")
|
|
||||||
.Annotation("Sqlite:Autoincrement", true)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
Name = table.Column<string>(name: "name", maxLength: 100, nullable: true, comment: "用户名称"),
|
|
||||||
Email = table.Column<string>(name: "email", maxLength: 200, nullable: true, comment: "用户邮箱"),
|
|
||||||
CreatedAt = table.Column<DateTime>(name: "created-at", nullable: false, comment: "创建时间"),
|
|
||||||
UpdatedAt = table.Column<DateTime>(name: "updated-at", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-user", x => x.Id);
|
|
||||||
},
|
|
||||||
comment: "用户实体,演示数据库 CRUD 操作");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "weather-forecast",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(name: "id", nullable: false, comment: "天气预报主键")
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1")
|
|
||||||
.Annotation("Sqlite:Autoincrement", true)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
Date = table.Column<DateOnly>(name: "date", nullable: false, comment: "预报日期"),
|
|
||||||
TemperatureC = table.Column<int>(name: "temperature-c", nullable: false, comment: "摄氏温度"),
|
|
||||||
Summary = table.Column<string>(name: "summary", maxLength: 200, nullable: true, comment: "天气摘要"),
|
|
||||||
CreatedAt = table.Column<DateTime>(name: "created-at", nullable: false, comment: "创建时间"),
|
|
||||||
UpdatedAt = table.Column<DateTime>(name: "updated-at", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-weather-forecast", x => x.Id);
|
|
||||||
},
|
|
||||||
comment: "天气预报数据实体");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(name: "weather-forecast");
|
|
||||||
migrationBuilder.DropTable(name: "user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,113 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260515072045_AutoMigration_20260515152037")]
|
|
||||||
partial class AutoMigration_20260515152037
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.0");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260515152037 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "phone-number",
|
|
||||||
table: "user",
|
|
||||||
type: "TEXT",
|
|
||||||
maxLength: 50,
|
|
||||||
nullable: true,
|
|
||||||
comment: "电话号码");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "phone-number",
|
|
||||||
table: "user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,173 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260515085847_AutoMigration_20260515165835")]
|
|
||||||
partial class AutoMigration_20260515165835
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.0");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260515165835 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "api-refresh-token",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<long>(type: "INTEGER", nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
userid = table.Column<int>(name: "user-id", type: "INTEGER", nullable: false),
|
|
||||||
tokenhash = table.Column<string>(name: "token-hash", type: "TEXT", maxLength: 128, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "TEXT", nullable: false),
|
|
||||||
expiresat = table.Column<DateTime>(name: "expires-at", type: "TEXT", nullable: false),
|
|
||||||
revokedat = table.Column<DateTime>(name: "revoked-at", type: "TEXT", nullable: true),
|
|
||||||
replacedbytokenhash = table.Column<string>(name: "replaced-by-token-hash", type: "TEXT", maxLength: 128, nullable: true),
|
|
||||||
device = table.Column<string>(type: "TEXT", maxLength: 200, nullable: true),
|
|
||||||
ipaddress = table.Column<string>(name: "ip-address", type: "TEXT", maxLength: 64, nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-api-refresh-token", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "API refresh token");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-hash",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "token-hash",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-user-id",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "user-id");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "api-refresh-token");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,179 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260520083230_AutoMigration_20260520163216")]
|
|
||||||
partial class AutoMigration_20260520163216
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.7");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260520163216 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user",
|
|
||||||
type: "TEXT",
|
|
||||||
maxLength: 200,
|
|
||||||
nullable: true,
|
|
||||||
comment: "密码哈希值");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,352 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260521080213_AddFileLibrary")]
|
|
||||||
partial class AddFileLibrary
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.7");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddFileLibrary : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-library-root",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "INTEGER", nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
path = table.Column<string>(type: "TEXT", maxLength: 1024, nullable: false),
|
|
||||||
displayname = table.Column<string>(name: "display-name", type: "TEXT", maxLength: 200, nullable: false),
|
|
||||||
isenabled = table.Column<bool>(name: "is-enabled", type: "INTEGER", nullable: false),
|
|
||||||
isavailable = table.Column<bool>(name: "is-available", type: "INTEGER", nullable: false, defaultValue: true),
|
|
||||||
scanintervalminutes = table.Column<int>(name: "scan-interval-minutes", type: "INTEGER", nullable: false),
|
|
||||||
lastscanstartedat = table.Column<DateTime>(name: "last-scan-started-at", type: "TEXT", nullable: true),
|
|
||||||
lastscancompletedat = table.Column<DateTime>(name: "last-scan-completed-at", type: "TEXT", nullable: true),
|
|
||||||
lastscanerror = table.Column<string>(name: "last-scan-error", type: "TEXT", maxLength: 2000, nullable: true),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "TEXT", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "TEXT", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-library-root", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "文件库根目录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-file-record",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "INTEGER", nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "INTEGER", nullable: false),
|
|
||||||
filename = table.Column<string>(name: "file-name", type: "TEXT", maxLength: 260, nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "TEXT", maxLength: 1024, nullable: false),
|
|
||||||
absolutepath = table.Column<string>(name: "absolute-path", type: "TEXT", maxLength: 2048, nullable: false),
|
|
||||||
extension = table.Column<string>(type: "TEXT", maxLength: 32, nullable: false),
|
|
||||||
sizebytes = table.Column<long>(name: "size-bytes", type: "INTEGER", nullable: false),
|
|
||||||
lastwritetimeutc = table.Column<DateTime>(name: "last-write-time-utc", type: "TEXT", nullable: false),
|
|
||||||
mediatype = table.Column<string>(name: "media-type", type: "TEXT", maxLength: 20, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "TEXT", maxLength: 100, nullable: false),
|
|
||||||
exists = table.Column<bool>(type: "INTEGER", nullable: false),
|
|
||||||
lastseenat = table.Column<DateTime>(name: "last-seen-at", type: "TEXT", nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "TEXT", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "TEXT", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-file-record", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件库文件记录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-absolute-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "absolute-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-media-type-exists",
|
|
||||||
table: "managed-file-record",
|
|
||||||
columns: new[] { "media-type", "exists" });
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-root-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-library-root-path",
|
|
||||||
table: "managed-library-root",
|
|
||||||
column: "path",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-library-root");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,368 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260522082814_AutoMigration_20260522162758")]
|
|
||||||
partial class AutoMigration_20260522162758
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.7");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<string>("ThumbnailPath")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("thumbnail-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260522162758 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "last-played-at",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "TEXT",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "TEXT",
|
|
||||||
maxLength: 512,
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<double>(
|
|
||||||
name: "video-duration",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "REAL",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-last-played-at",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "last-played-at");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-last-played-at",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "last-played-at",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "video-duration",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,442 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260522084259_AddThumbnailMap")]
|
|
||||||
partial class AddThumbnailMap
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.7");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddThumbnailMap : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "INTEGER",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-thumbnail-map",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "INTEGER", nullable: false)
|
|
||||||
.Annotation("Sqlite:Autoincrement", true),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "INTEGER", nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "TEXT", maxLength: 1024, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "TEXT", maxLength: 100, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "TEXT", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "TEXT", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-thumbnail-map", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-thumbnail-map_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件缩略图映射记录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-relative-path",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "relative-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-root-id",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id",
|
|
||||||
principalTable: "managed-thumbnail-map",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.SetNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-thumbnail-map");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "TEXT",
|
|
||||||
maxLength: 512,
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,446 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260522092304_AddPlaybackPosition")]
|
|
||||||
partial class AddPlaybackPosition
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.7");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddPlaybackPosition : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<double>(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "REAL",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,453 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
[Migration("20260523023607_AutoMigration_20260523103531")]
|
|
||||||
partial class AutoMigration_20260523103531
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.7");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("FileCreationTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-creation-time-utc");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("FileCreationTimeUtc")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260523103531 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "TEXT",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "file-creation-time-utc");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,450 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SQLite
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqliteAppDataContext))]
|
|
||||||
partial class SqliteAppDataContextModelSnapshot : ModelSnapshot
|
|
||||||
{
|
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.7");
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("FileCreationTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-creation-time-utc");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("REAL")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("FileCreationTimeUtc")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("INTEGER")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("TEXT")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,184 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqlServerAppDataContext))]
|
|
||||||
[Migration("20260520082607_AutoMigration_20260520162543")]
|
|
||||||
partial class AutoMigration_20260520162543
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("nvarchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260520162543 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "api-refresh-token",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<long>(type: "bigint", nullable: false)
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1"),
|
|
||||||
userid = table.Column<int>(name: "user-id", type: "int", nullable: false),
|
|
||||||
tokenhash = table.Column<string>(name: "token-hash", type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime2", nullable: false),
|
|
||||||
expiresat = table.Column<DateTime>(name: "expires-at", type: "datetime2", nullable: false),
|
|
||||||
revokedat = table.Column<DateTime>(name: "revoked-at", type: "datetime2", nullable: true),
|
|
||||||
replacedbytokenhash = table.Column<string>(name: "replaced-by-token-hash", type: "nvarchar(128)", maxLength: 128, nullable: true),
|
|
||||||
device = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
|
||||||
ipaddress = table.Column<string>(name: "ip-address", type: "nvarchar(64)", maxLength: 64, nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-api-refresh-token", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "API refresh token");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "user",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false, comment: "用户主键")
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1"),
|
|
||||||
name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true, comment: "用户名称"),
|
|
||||||
email = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true, comment: "用户邮箱"),
|
|
||||||
phonenumber = table.Column<string>(name: "phone-number", type: "nvarchar(50)", maxLength: 50, nullable: true, comment: "电话号码"),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime2", nullable: false, comment: "创建时间"),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime2", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-user", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "用户实体,演示数据库 CRUD 操作");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "weather-forecast",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false, comment: "天气预报主键")
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1"),
|
|
||||||
date = table.Column<DateOnly>(type: "date", nullable: false, comment: "预报日期"),
|
|
||||||
temperaturec = table.Column<int>(name: "temperature-c", type: "int", nullable: false, comment: "摄氏温度"),
|
|
||||||
summary = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true, comment: "天气摘要"),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime2", nullable: false, comment: "创建时间"),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime2", nullable: false, comment: "更新时间")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-weather-forecast", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "天气预报数据实体");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-hash",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "token-hash",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-api-refresh-token-user-id",
|
|
||||||
table: "api-refresh-token",
|
|
||||||
column: "user-id");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "api-refresh-token");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "user");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "weather-forecast");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,190 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqlServerAppDataContext))]
|
|
||||||
[Migration("20260520083242_AutoMigration_20260520163216")]
|
|
||||||
partial class AutoMigration_20260520163216
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("nvarchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260520163216 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user",
|
|
||||||
type: "nvarchar(200)",
|
|
||||||
maxLength: 200,
|
|
||||||
nullable: true,
|
|
||||||
comment: "密码哈希值");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "password-hash",
|
|
||||||
table: "user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,383 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqlServerAppDataContext))]
|
|
||||||
[Migration("20260522082829_AutoMigration_20260522162758")]
|
|
||||||
partial class AutoMigration_20260522162758
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("nvarchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("nvarchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("nvarchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("nvarchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<string>("ThumbnailPath")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("nvarchar(512)")
|
|
||||||
.HasColumnName("thumbnail-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("float")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("nvarchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("nvarchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,110 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260522162758 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-library-root",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1"),
|
|
||||||
path = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: false),
|
|
||||||
displayname = table.Column<string>(name: "display-name", type: "nvarchar(200)", maxLength: 200, nullable: false),
|
|
||||||
isenabled = table.Column<bool>(name: "is-enabled", type: "bit", nullable: false),
|
|
||||||
isavailable = table.Column<bool>(name: "is-available", type: "bit", nullable: false, defaultValue: true),
|
|
||||||
scanintervalminutes = table.Column<int>(name: "scan-interval-minutes", type: "int", nullable: false),
|
|
||||||
lastscanstartedat = table.Column<DateTime>(name: "last-scan-started-at", type: "datetime2", nullable: true),
|
|
||||||
lastscancompletedat = table.Column<DateTime>(name: "last-scan-completed-at", type: "datetime2", nullable: true),
|
|
||||||
lastscanerror = table.Column<string>(name: "last-scan-error", type: "nvarchar(2000)", maxLength: 2000, nullable: true),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime2", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime2", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-library-root", x => x.id);
|
|
||||||
},
|
|
||||||
comment: "文件库根目录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-file-record",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1"),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "int", nullable: false),
|
|
||||||
filename = table.Column<string>(name: "file-name", type: "nvarchar(260)", maxLength: 260, nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "nvarchar(1024)", maxLength: 1024, nullable: false),
|
|
||||||
absolutepath = table.Column<string>(name: "absolute-path", type: "nvarchar(2048)", maxLength: 2048, nullable: false),
|
|
||||||
extension = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
|
|
||||||
sizebytes = table.Column<long>(name: "size-bytes", type: "bigint", nullable: false),
|
|
||||||
lastwritetimeutc = table.Column<DateTime>(name: "last-write-time-utc", type: "datetime2", nullable: false),
|
|
||||||
mediatype = table.Column<string>(name: "media-type", type: "nvarchar(20)", maxLength: 20, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "nvarchar(100)", maxLength: 100, nullable: false),
|
|
||||||
exists = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
lastseenat = table.Column<DateTime>(name: "last-seen-at", type: "datetime2", nullable: false),
|
|
||||||
thumbnailpath = table.Column<string>(name: "thumbnail-path", type: "nvarchar(512)", maxLength: 512, nullable: true),
|
|
||||||
videoduration = table.Column<double>(name: "video-duration", type: "float", nullable: true),
|
|
||||||
lastplayedat = table.Column<DateTime>(name: "last-played-at", type: "datetime2", nullable: true),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime2", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime2", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-file-record", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件库文件记录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-absolute-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "absolute-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-last-played-at",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "last-played-at");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-media-type-exists",
|
|
||||||
table: "managed-file-record",
|
|
||||||
columns: new[] { "media-type", "exists" });
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-root-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-library-root-path",
|
|
||||||
table: "managed-library-root",
|
|
||||||
column: "path",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-library-root");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,459 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqlServerAppDataContext))]
|
|
||||||
[Migration("20260522084325_AddThumbnailMap")]
|
|
||||||
partial class AddThumbnailMap
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("nvarchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("nvarchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("nvarchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("nvarchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("float")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("nvarchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("nvarchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddThumbnailMap : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "int",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "managed-thumbnail-map",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("SqlServer:Identity", "1, 1"),
|
|
||||||
libraryrootid = table.Column<int>(name: "library-root-id", type: "int", nullable: false),
|
|
||||||
relativepath = table.Column<string>(name: "relative-path", type: "nvarchar(1024)", maxLength: 1024, nullable: false),
|
|
||||||
contenttype = table.Column<string>(name: "content-type", type: "nvarchar(100)", maxLength: 100, nullable: false),
|
|
||||||
createdat = table.Column<DateTime>(name: "created-at", type: "datetime2", nullable: false),
|
|
||||||
updatedat = table.Column<DateTime>(name: "updated-at", type: "datetime2", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk-managed-thumbnail-map", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_managed-thumbnail-map_managed-library-root_library-root-id",
|
|
||||||
column: x => x.libraryrootid,
|
|
||||||
principalTable: "managed-library-root",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
},
|
|
||||||
comment: "文件缩略图映射记录");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-relative-path",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "relative-path",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-thumbnail-map-root-id",
|
|
||||||
table: "managed-thumbnail-map",
|
|
||||||
column: "library-root-id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "thumbnail-id",
|
|
||||||
principalTable: "managed-thumbnail-map",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.SetNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_managed-file-record_managed-thumbnail-map_thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "managed-thumbnail-map");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "thumbnail-id",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "thumbnail-path",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "nvarchar(512)",
|
|
||||||
maxLength: 512,
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,463 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqlServerAppDataContext))]
|
|
||||||
[Migration("20260522092317_AddPlaybackPosition")]
|
|
||||||
partial class AddPlaybackPosition
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("nvarchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("nvarchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("nvarchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("nvarchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("float")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("float")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("nvarchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("nvarchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddPlaybackPosition : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<double>(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "float",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "playback-position",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,470 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using FileShare_EFCore.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
[DbContext(typeof(SqlServerAppDataContext))]
|
|
||||||
[Migration("20260523023625_AutoMigration_20260523103531")]
|
|
||||||
partial class AutoMigration_20260523103531
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ApiRefreshTokenEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<long>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("Device")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("device");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ExpiresAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("expires-at");
|
|
||||||
|
|
||||||
b.Property<string>("IpAddress")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)")
|
|
||||||
.HasColumnName("ip-address");
|
|
||||||
|
|
||||||
b.Property<string>("ReplacedByTokenHash")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("replaced-by-token-hash");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("RevokedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("revoked-at");
|
|
||||||
|
|
||||||
b.Property<string>("TokenHash")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("nvarchar(128)")
|
|
||||||
.HasColumnName("token-hash");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("user-id");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-api-refresh-token");
|
|
||||||
|
|
||||||
b.HasIndex("TokenHash")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-hash");
|
|
||||||
|
|
||||||
b.HasIndex("UserId")
|
|
||||||
.HasDatabaseName("idx-api-refresh-token-user-id");
|
|
||||||
|
|
||||||
b.ToTable("api-refresh-token", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("API refresh token");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("AbsolutePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2048)
|
|
||||||
.HasColumnType("nvarchar(2048)")
|
|
||||||
.HasColumnName("absolute-path");
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<bool>("Exists")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("exists");
|
|
||||||
|
|
||||||
b.Property<string>("Extension")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("nvarchar(32)")
|
|
||||||
.HasColumnName("extension");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("FileCreationTimeUtc")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("file-creation-time-utc");
|
|
||||||
|
|
||||||
b.Property<string>("FileName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(260)
|
|
||||||
.HasColumnType("nvarchar(260)")
|
|
||||||
.HasColumnName("file-name");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastPlayedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-played-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastSeenAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-seen-at");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastWriteTimeUtc")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-write-time-utc");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("MediaType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(20)
|
|
||||||
.HasColumnType("nvarchar(20)")
|
|
||||||
.HasColumnName("media-type");
|
|
||||||
|
|
||||||
b.Property<double?>("PlaybackPosition")
|
|
||||||
.HasColumnType("float")
|
|
||||||
.HasColumnName("playback-position");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<long>("SizeBytes")
|
|
||||||
.HasColumnType("bigint")
|
|
||||||
.HasColumnName("size-bytes");
|
|
||||||
|
|
||||||
b.Property<int?>("ThumbnailId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("thumbnail-id");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.Property<double?>("VideoDuration")
|
|
||||||
.HasColumnType("float")
|
|
||||||
.HasColumnName("video-duration");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-file-record");
|
|
||||||
|
|
||||||
b.HasIndex("AbsolutePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-file-record-absolute-path");
|
|
||||||
|
|
||||||
b.HasIndex("FileCreationTimeUtc")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-file-creation-time");
|
|
||||||
|
|
||||||
b.HasIndex("LastPlayedAt")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-last-played-at");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("ThumbnailId")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-thumbnail-id");
|
|
||||||
|
|
||||||
b.HasIndex("MediaType", "Exists")
|
|
||||||
.HasDatabaseName("idx-managed-file-record-media-type-exists");
|
|
||||||
|
|
||||||
b.ToTable("managed-file-record", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库文件记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("display-name");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAvailable")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(true)
|
|
||||||
.HasColumnName("is-available");
|
|
||||||
|
|
||||||
b.Property<bool>("IsEnabled")
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasColumnName("is-enabled");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanCompletedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-completed-at");
|
|
||||||
|
|
||||||
b.Property<string>("LastScanError")
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("nvarchar(2000)")
|
|
||||||
.HasColumnName("last-scan-error");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastScanStartedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("last-scan-started-at");
|
|
||||||
|
|
||||||
b.Property<string>("Path")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("path");
|
|
||||||
|
|
||||||
b.Property<int>("ScanIntervalMinutes")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("scan-interval-minutes");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-library-root");
|
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-library-root-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-library-root", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件库根目录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ContentType")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("content-type");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at");
|
|
||||||
|
|
||||||
b.Property<int>("LibraryRootId")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("library-root-id");
|
|
||||||
|
|
||||||
b.Property<string>("RelativePath")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)")
|
|
||||||
.HasColumnName("relative-path");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-managed-thumbnail-map");
|
|
||||||
|
|
||||||
b.HasIndex("LibraryRootId")
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-root-id");
|
|
||||||
|
|
||||||
b.HasIndex("RelativePath")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("idx-managed-thumbnail-map-relative-path");
|
|
||||||
|
|
||||||
b.ToTable("managed-thumbnail-map", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("文件缩略图映射记录");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.UserEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("用户主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("email")
|
|
||||||
.HasComment("用户邮箱");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)")
|
|
||||||
.HasColumnName("name")
|
|
||||||
.HasComment("用户名称");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("password-hash")
|
|
||||||
.HasComment("密码哈希值");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasMaxLength(50)
|
|
||||||
.HasColumnType("nvarchar(50)")
|
|
||||||
.HasColumnName("phone-number")
|
|
||||||
.HasComment("电话号码");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-user");
|
|
||||||
|
|
||||||
b.ToTable("user", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("用户实体,演示数据库 CRUD 操作");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.WeatherForecastEntity", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("id")
|
|
||||||
.HasComment("天气预报主键");
|
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("created-at")
|
|
||||||
.HasComment("创建时间");
|
|
||||||
|
|
||||||
b.Property<DateOnly>("Date")
|
|
||||||
.HasColumnType("date")
|
|
||||||
.HasColumnName("date")
|
|
||||||
.HasComment("预报日期");
|
|
||||||
|
|
||||||
b.Property<string>("Summary")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)")
|
|
||||||
.HasColumnName("summary")
|
|
||||||
.HasComment("天气摘要");
|
|
||||||
|
|
||||||
b.Property<int>("TemperatureC")
|
|
||||||
.HasColumnType("int")
|
|
||||||
.HasColumnName("temperature-c")
|
|
||||||
.HasComment("摄氏温度");
|
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("updated-at")
|
|
||||||
.HasComment("更新时间");
|
|
||||||
|
|
||||||
b.HasKey("Id")
|
|
||||||
.HasName("pk-weather-forecast");
|
|
||||||
|
|
||||||
b.ToTable("weather-forecast", t =>
|
|
||||||
{
|
|
||||||
t.HasComment("天气预报数据实体");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedFileRecord", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedThumbnailMap", "Thumbnail")
|
|
||||||
.WithMany("Files")
|
|
||||||
.HasForeignKey("ThumbnailId")
|
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnail");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("FileShare_EFCore.Models.ManagedLibraryRoot", "LibraryRoot")
|
|
||||||
.WithMany("Thumbnails")
|
|
||||||
.HasForeignKey("LibraryRootId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("LibraryRoot");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedLibraryRoot", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
|
|
||||||
b.Navigation("Thumbnails");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("FileShare_EFCore.Models.ManagedThumbnailMap", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Files");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace FileShare_EFCore.Migrations.SqlServer
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AutoMigration_20260523103531 : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record",
|
|
||||||
type: "datetime2",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record",
|
|
||||||
column: "file-creation-time-utc");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "idx-managed-file-record-file-creation-time",
|
|
||||||
table: "managed-file-record");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "file-creation-time-utc",
|
|
||||||
table: "managed-file-record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user