remove adapter for more ease of development
This commit is contained in:
@@ -1,6 +0,0 @@
|
||||
namespace adapter;
|
||||
|
||||
public class Class1
|
||||
{
|
||||
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
138
tagvid/AdapterContext.cs
Normal file
138
tagvid/AdapterContext.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using Db.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
public class AdapterContext : DbContext
|
||||
{
|
||||
public AdapterContext(DbContextOptions<AdapterContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
// Configure your entity mappings here
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// primary keys
|
||||
modelBuilder.Entity<Tag>().HasKey(t => t.Name);
|
||||
modelBuilder.Entity<Video>().HasKey(v => v.Id);
|
||||
modelBuilder.Entity<VideoMetadata>().HasKey(vm => vm.Id);
|
||||
modelBuilder.Entity<Setting>().HasKey(s => s.Name);
|
||||
|
||||
// Id of VideoMetadata is the same as Video Id
|
||||
modelBuilder.Entity<VideoMetadata>()
|
||||
.Property(vm => vm.Id)
|
||||
.ValueGeneratedNever(); // Id is set by the Video entity
|
||||
|
||||
// Id of Video is set by the database
|
||||
modelBuilder.Entity<Video>()
|
||||
.Property(v => v.Id)
|
||||
.ValueGeneratedOnAdd(); // Id is generated by the database
|
||||
|
||||
// Id of Setting is the same as SettingName enum value
|
||||
modelBuilder.Entity<Setting>()
|
||||
.Property(s => s.Name)
|
||||
.HasConversion<string>(); // Store enum as string in the database
|
||||
|
||||
// relationships
|
||||
|
||||
// Video can have one Metadata (can be null)
|
||||
modelBuilder.Entity<Video>()
|
||||
.HasOne(v => v.Metadata)
|
||||
.WithOne(vm => vm.Video)
|
||||
.HasForeignKey<VideoMetadata>(vm => vm.Id);
|
||||
|
||||
// Video can have many Tags
|
||||
modelBuilder.Entity<Video>()
|
||||
.HasMany(v => v.Tags)
|
||||
.WithMany(t => t.Videos)
|
||||
.UsingEntity(j => j.ToTable("VideoTags")); // Join table for many-to-many relationship
|
||||
|
||||
// Setting has a unique Name
|
||||
modelBuilder.Entity<Setting>()
|
||||
.HasIndex(s => s.Name)
|
||||
.IsUnique();
|
||||
|
||||
// Setting name enum is stored as string
|
||||
modelBuilder.Entity<Setting>()
|
||||
.Property(s => s.Name)
|
||||
.HasConversion<string>();
|
||||
|
||||
// Setting value is stored as string
|
||||
modelBuilder.Entity<Setting>()
|
||||
.Property(s => s.Value)
|
||||
.IsRequired();
|
||||
|
||||
// Video relative path is required
|
||||
modelBuilder.Entity<Video>()
|
||||
.Property(v => v.RelativePath)
|
||||
.IsRequired();
|
||||
|
||||
// VideoMetadata properties
|
||||
modelBuilder.Entity<VideoMetadata>()
|
||||
.Property(vm => vm.Title)
|
||||
.IsRequired();
|
||||
|
||||
modelBuilder.Entity<VideoMetadata>()
|
||||
.Property(vm => vm.Duration)
|
||||
.IsRequired();
|
||||
|
||||
// VideoMetadata duration is defaulted to zero if not set
|
||||
modelBuilder.Entity<VideoMetadata>()
|
||||
.Property(vm => vm.Duration)
|
||||
.HasDefaultValue(TimeSpan.Zero);
|
||||
|
||||
// VideoMetadata width and height are required
|
||||
modelBuilder.Entity<VideoMetadata>()
|
||||
.Property(vm => vm.Width)
|
||||
.IsRequired();
|
||||
|
||||
modelBuilder.Entity<VideoMetadata>()
|
||||
.Property(vm => vm.Height)
|
||||
.IsRequired();
|
||||
|
||||
// Tag name is required
|
||||
modelBuilder.Entity<Tag>()
|
||||
.Property(t => t.Name)
|
||||
.IsRequired();
|
||||
|
||||
// Tag name is unique
|
||||
modelBuilder.Entity<Tag>()
|
||||
.HasIndex(t => t.Name)
|
||||
.IsUnique();
|
||||
|
||||
}
|
||||
|
||||
// Tags a video can have (e.g. "funny", "cat", "dog")
|
||||
public DbSet<Tag> Tags { get; set; }
|
||||
|
||||
// Videos with tags, relative paths, and other metadata
|
||||
public DbSet<Video> Videos { get; set; }
|
||||
|
||||
// Video metadata, such as title, description, and duration
|
||||
public DbSet<VideoMetadata> VideoMetadatas { get; set; }
|
||||
// Settings for the adapter, such as video path
|
||||
public DbSet<Setting> Settings { get; set; }
|
||||
|
||||
public async Task<T?> GetSettingAsync<T>(SettingName settingName)
|
||||
{
|
||||
var setting = await Settings.FindAsync(settingName);
|
||||
return setting != null ? (T?)Convert.ChangeType(setting.Value, typeof(T)) : default;
|
||||
}
|
||||
|
||||
public async Task SetSettingAsync<T>(SettingName settingName, T value)
|
||||
{
|
||||
var setting = await Settings.FindAsync(settingName);
|
||||
if (setting == null)
|
||||
{
|
||||
setting = new Setting { Name = settingName, Value = value?.ToString() ?? string.Empty };
|
||||
Settings.Add(setting);
|
||||
}
|
||||
else
|
||||
{
|
||||
setting.Value = value?.ToString() ?? string.Empty;
|
||||
Settings.Update(setting);
|
||||
}
|
||||
await SaveChangesAsync();
|
||||
}
|
||||
}
|
145
tagvid/Migrations/20250726102958_InitialMigration.Designer.cs
generated
Normal file
145
tagvid/Migrations/20250726102958_InitialMigration.Designer.cs
generated
Normal file
@@ -0,0 +1,145 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace tagvid.Migrations
|
||||
{
|
||||
[DbContext(typeof(AdapterContext))]
|
||||
[Migration("20250726102958_InitialMigration")]
|
||||
partial class InitialMigration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.7")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Db.Models.Setting", b =>
|
||||
{
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Name");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.Tag", b =>
|
||||
{
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Name");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Tags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.Video", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("RelativePath")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Videos");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.VideoMetadata", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<TimeSpan>("Duration")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("time")
|
||||
.HasDefaultValue(new TimeSpan(0, 0, 0, 0, 0));
|
||||
|
||||
b.Property<int>("Height")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<int>("Width")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("VideoMetadatas");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TagVideo", b =>
|
||||
{
|
||||
b.Property<string>("TagsName")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("VideosId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("TagsName", "VideosId");
|
||||
|
||||
b.HasIndex("VideosId");
|
||||
|
||||
b.ToTable("VideoTags", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.VideoMetadata", b =>
|
||||
{
|
||||
b.HasOne("Db.Models.Video", "Video")
|
||||
.WithOne("Metadata")
|
||||
.HasForeignKey("Db.Models.VideoMetadata", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Video");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TagVideo", b =>
|
||||
{
|
||||
b.HasOne("Db.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsName")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Db.Models.Video", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("VideosId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.Video", b =>
|
||||
{
|
||||
b.Navigation("Metadata");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
131
tagvid/Migrations/20250726102958_InitialMigration.cs
Normal file
131
tagvid/Migrations/20250726102958_InitialMigration.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace tagvid.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialMigration : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Settings",
|
||||
columns: table => new
|
||||
{
|
||||
Name = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
Value = table.Column<string>(type: "nvarchar(max)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Settings", x => x.Name);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Tags",
|
||||
columns: table => new
|
||||
{
|
||||
Name = table.Column<string>(type: "nvarchar(450)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Tags", x => x.Name);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Videos",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
RelativePath = table.Column<string>(type: "nvarchar(max)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Videos", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "VideoMetadatas",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
Title = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Duration = table.Column<TimeSpan>(type: "time", nullable: false, defaultValue: new TimeSpan(0, 0, 0, 0, 0)),
|
||||
Width = table.Column<int>(type: "int", nullable: false),
|
||||
Height = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_VideoMetadatas", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_VideoMetadatas_Videos_Id",
|
||||
column: x => x.Id,
|
||||
principalTable: "Videos",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "VideoTags",
|
||||
columns: table => new
|
||||
{
|
||||
TagsName = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||
VideosId = table.Column<string>(type: "nvarchar(450)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_VideoTags", x => new { x.TagsName, x.VideosId });
|
||||
table.ForeignKey(
|
||||
name: "FK_VideoTags_Tags_TagsName",
|
||||
column: x => x.TagsName,
|
||||
principalTable: "Tags",
|
||||
principalColumn: "Name",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_VideoTags_Videos_VideosId",
|
||||
column: x => x.VideosId,
|
||||
principalTable: "Videos",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Settings_Name",
|
||||
table: "Settings",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tags_Name",
|
||||
table: "Tags",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_VideoTags_VideosId",
|
||||
table: "VideoTags",
|
||||
column: "VideosId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Settings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "VideoMetadatas");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "VideoTags");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Tags");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Videos");
|
||||
}
|
||||
}
|
||||
}
|
142
tagvid/Migrations/AdapterContextModelSnapshot.cs
Normal file
142
tagvid/Migrations/AdapterContextModelSnapshot.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace tagvid.Migrations
|
||||
{
|
||||
[DbContext(typeof(AdapterContext))]
|
||||
partial class AdapterContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.7")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Db.Models.Setting", b =>
|
||||
{
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Name");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.Tag", b =>
|
||||
{
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Name");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Tags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.Video", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("RelativePath")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Videos");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.VideoMetadata", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<TimeSpan>("Duration")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("time")
|
||||
.HasDefaultValue(new TimeSpan(0, 0, 0, 0, 0));
|
||||
|
||||
b.Property<int>("Height")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<int>("Width")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("VideoMetadatas");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TagVideo", b =>
|
||||
{
|
||||
b.Property<string>("TagsName")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("VideosId")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("TagsName", "VideosId");
|
||||
|
||||
b.HasIndex("VideosId");
|
||||
|
||||
b.ToTable("VideoTags", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.VideoMetadata", b =>
|
||||
{
|
||||
b.HasOne("Db.Models.Video", "Video")
|
||||
.WithOne("Metadata")
|
||||
.HasForeignKey("Db.Models.VideoMetadata", "Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Video");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TagVideo", b =>
|
||||
{
|
||||
b.HasOne("Db.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsName")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Db.Models.Video", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("VideosId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Db.Models.Video", b =>
|
||||
{
|
||||
b.Navigation("Metadata");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllersWithViews();
|
||||
|
||||
// Configure Entity Framework Core with SQL Server
|
||||
builder.Services.AddDbContext<AdapterContext>(options =>
|
||||
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
8
tagvid/SettingName.cs
Normal file
8
tagvid/SettingName.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
public enum SettingName
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a the absolute path of the folder where videos are stored.
|
||||
/// </summary>
|
||||
VideoPath,
|
||||
|
||||
}
|
13
tagvid/db/models/Setting.cs
Normal file
13
tagvid/db/models/Setting.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Db.Models;
|
||||
|
||||
public class Setting
|
||||
{
|
||||
public required SettingName Name { get; set; }
|
||||
public required string Value { get; set; }
|
||||
|
||||
// methods to convert Value to specific types that are not connected to entity framework
|
||||
public T GetValue<T>()
|
||||
{
|
||||
return (T)Convert.ChangeType(Value, typeof(T));
|
||||
}
|
||||
}
|
9
tagvid/db/models/Tag.cs
Normal file
9
tagvid/db/models/Tag.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Db.Models;
|
||||
|
||||
public class Tag
|
||||
{
|
||||
// We use the name of the tag as the Id to ensure uniqueness
|
||||
public required string Name { get; set; }
|
||||
|
||||
public ICollection<Video> Videos { get; set; } = [];
|
||||
}
|
15
tagvid/db/models/Video.cs
Normal file
15
tagvid/db/models/Video.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Db.Models;
|
||||
|
||||
public class Video
|
||||
{
|
||||
// Disable warning as Id is required but not set in the constructor.
|
||||
// This is to ensure that the Id is set by the database when the entity is added
|
||||
#pragma warning disable CS8618
|
||||
public string Id { get; set; }
|
||||
#pragma warning restore CS8618
|
||||
public required string RelativePath { get; set; }
|
||||
|
||||
|
||||
public ICollection<Tag> Tags { get; set; } = [];
|
||||
public VideoMetadata? Metadata { get; set; }
|
||||
}
|
20
tagvid/db/models/VideoMetadata.cs
Normal file
20
tagvid/db/models/VideoMetadata.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace Db.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents metadata for a video, such as title, duration, resolution, etc.
|
||||
/// So we dont need to load the video file to get this information.
|
||||
/// </summary>
|
||||
public class VideoMetadata
|
||||
{
|
||||
// Disable warning as Id is required but not set in the constructor.
|
||||
// This is to ensure that the Id is set by the database when the entity is added
|
||||
#pragma warning disable CS8618
|
||||
public string Id { get; set; }
|
||||
#pragma warning restore CS8618
|
||||
|
||||
public required string Title { get; set; }
|
||||
public TimeSpan Duration { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public Video? Video { get; set; }
|
||||
}
|
@@ -1,7 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\adapter\adapter.csproj" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
Reference in New Issue
Block a user