add repository with mysql and entities

This commit is contained in:
Oleksandr Bezdieniezhnykh
2024-07-16 14:18:55 +03:00
parent 32c92fedf2
commit bfbfdf6658
18 changed files with 331 additions and 3 deletions
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="linq2db" Version="5.4.1" />
<PackageReference Include="MySqlConnector" Version="2.3.7" />
</ItemGroup>
</Project>
@@ -0,0 +1,12 @@
using Azaion.Repository.Entities;
using LinqToDB;
using LinqToDB.Data;
namespace Azaion.Repository;
public class AzaionDbSql(DataOptions dataOptions) : DataConnection(dataOptions)
{
public ITable<Media> Medias => this.GetTable<Media>();
public ITable<User> Users => this.GetTable<User>();
public ITable<Annotation> Annotations => this.GetTable<Annotation>();
}
@@ -0,0 +1,26 @@
using Azaion.Repository.Entities;
using LinqToDB.Mapping;
namespace Azaion.Repository;
public static class AzaionDbSqlSchemaHolder
{
public static readonly MappingSchema MappingSchema;
static AzaionDbSqlSchemaHolder()
{
MappingSchema = new MappingSchema();
var builder = new FluentMappingBuilder(MappingSchema);
builder.Entity<User>()
.HasIdentity(x => x.Id);
builder.Entity<Media>()
.HasIdentity(x => x.Id);
builder.Entity<Annotation>()
.HasIdentity(x => x.Id);
builder.Build();
}
}
@@ -0,0 +1,7 @@
namespace Azaion.Repository.DTO;
public class ConnectionStrings
{
public string? FraudDb { get; set; }
public string? FraudDbMsSql { get; set; }
}
@@ -0,0 +1,9 @@
namespace Azaion.Video.DTO;
public enum MediaStatusEnum
{
None = 0,
Uploaded = 10,
Annotating = 20,
Annotated = 30
}
@@ -0,0 +1,11 @@
using Azaion.Video.DTO;
namespace Azaion.Repository.DTO;
public class VideoDto
{
public Guid Id { get; set; }
public string Path { get; set; } = null!;
public MediaStatusEnum MediaStatus { get; set; }
public DateTime CreatedDate { get; set; }
}
@@ -0,0 +1,48 @@
using System.Diagnostics;
using LinqToDB;
namespace Azaion.Repository;
public interface IDbFactory
{
Task<T> Run<T>(Func<AzaionDbSql, Task<T>> func);
Task Run(Func<AzaionDbSql, Task> func);
T Run<T>(Func<AzaionDbSql, T> func);
}
public class DbFactory : IDbFactory
{
private readonly DataOptions _dataOptions;
public DbFactory(string connectionString, bool useTracing = true)
{
if (string.IsNullOrEmpty(connectionString))
throw new ArgumentException("Empty connectionString", nameof(connectionString));
_dataOptions = new DataOptions()
.UseMySqlConnector(connectionString)
.UseMappingSchema(AzaionDbSqlSchemaHolder.MappingSchema);
if (useTracing)
_ = _dataOptions.UseTracing(TraceLevel.Info, t => Console.WriteLine(t.SqlText));
}
public async Task<T> Run<T>(Func<AzaionDbSql, Task<T>> func)
{
await using var db = new AzaionDbSql(_dataOptions);
return await func(db);
}
public async Task Run(Func<AzaionDbSql, Task> func)
{
await using var db = new AzaionDbSql(_dataOptions);
await func(db);
}
public T Run<T>(Func<AzaionDbSql, T> func)
{
using var db = new AzaionDbSql(_dataOptions);
return func(db);
}
}
@@ -0,0 +1,10 @@
namespace Azaion.Repository.Entities;
public class Annotation
{
public Guid Id { get; set; }
public Guid MediaId { get; set; }
public string ImagePath { get; set; } = null!;
public string LabelPath { get; set; } = null!;
public DateTime CreatedDate { get; set; }
}
@@ -0,0 +1,12 @@
using Azaion.Video.DTO;
namespace Azaion.Repository.Entities;
public class Media
{
public Guid Id { get; set; }
public string Path { get; set; } = null!;
public Guid? AnnotatorId { get; set; }
public MediaStatusEnum Status { get; set; }
public DateTime CreatedDate { get; set; }
}
@@ -0,0 +1,12 @@
namespace Azaion.Repository.Entities;
public class User
{
public Guid Id { get; set; }
public string Username { get; set; } = null!;
public string Email { get; set; } = null!;
public string PasswordHash { get; set; } = null!;
public string PasswordSalt { get; set; } = null!;
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
}
@@ -0,0 +1,6 @@
CREATE USER 'azaion-user' IDENTIFIED BY 'Aza1on@db123'
CREATE DATABASE azaion;
GRANT SELECT, INSERT, REFERENCES, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES
ON azaion.*
TO 'azaion-user';
GRANT FILE ON *.* TO 'azaion-user';
@@ -0,0 +1,34 @@
CREATE TABLE User (
Id CHAR(16) NOT NULL,
Username VARCHAR(255) NOT NULL,
Email VARCHAR(255) NOT NULL,
PasswordHash VARCHAR(255) NOT NULL,
PasswordSalt VARCHAR(255) NOT NULL,
CreatedDate DATETIME NOT NULL,
UpdatedDate DATETIME NOT NULL,
PRIMARY KEY (Id),
UNIQUE KEY (Username),
UNIQUE KEY (Email)
);
DROP TABLE Annotation;
DROP TABLE Media;
CREATE TABLE Media (
Id CHAR(16) NOT NULL,
Path VARCHAR(255) NOT NULL,
AnnotatorId CHAR(16) NULL,
Status INT NOT NULL, -- replace with actual enum values
CreatedDate DATETIME NOT NULL,
PRIMARY KEY (Id),
FOREIGN KEY (AnnotatorId) REFERENCES User(Id)
);
CREATE TABLE Annotation (
Id CHAR(16) NOT NULL,
MediaId CHAR(16) NOT NULL,
ImagePath VARCHAR(255) NOT NULL,
LabelPath VARCHAR(255) NOT NULL,
CreatedDate DATETIME NOT NULL,
PRIMARY KEY (Id),
FOREIGN KEY (MediaId) REFERENCES Media(Id)
);
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Azaion.Repository\Azaion.Repository.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,58 @@
using Azaion.Repository.DTO;
namespace Azaion.Video;
public interface IVideoManager
{
List<VideoDto> GetVideos();
void OpenVideo(Guid mediaId);
void CreateAnnotation(Guid mediaId, DateTime time)
{
}
void FinishAnnotation(Guid mediaId);
// after video ends, refresh list of free to edit videos.
// on attempt to open video, check whether it is already taken, if yes, then businessError, else take it to user
//
// Users
// Guid Username Email PasswordHash PasswordSalt CreatedDate UpdatedDate
//
// Media
// Guid Path UserId Status CreatedDate
//
// Annotations
// Guid MediaId ImagePath LabelPath CreatedDate
//
// Sftp Changes crawler
// Google Downloader
//
// Video_path User
//
// v01 NULL
// v02 NULL
// v03 NULL
// v04 NULL
// v05 user1
// v06 user1
// v07 user1
// v08 NULL
// v09 user2
// v10 user3
// v11 user3
// v12 NULL
// v13 user2
// v14 NULL
// v15
// v16
// v17
// v18
// v19
// v20
// v21
// v22
// v23
// v24
// v25
}
@@ -0,0 +1,36 @@
using Azaion.Repository;
using Azaion.Repository.DTO;
namespace Azaion.Video;
public class VideoManager(IDbFactory dbFactory) : IVideoManager
{
public List<VideoDto> GetVideos()
{
return dbFactory.Run(db => db.Medias
.Where(x => x.AnnotatorId != null)
.Select(x => new VideoDto
{
Id = x.Id,
Path = x.Path,
CreatedDate = x.CreatedDate,
MediaStatus = x.Status
})
.ToList());
}
public void OpenVideo(Guid mediaId)
{
throw new NotImplementedException();
}
public void OpenTestVideo()
{
}
public void FinishAnnotation(Guid mediaId)
{
throw new NotImplementedException();
}
}
+12
View File
@@ -2,6 +2,10 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.WebService", "Azaion.WebService\Azaion.WebService.csproj", "{1D56907A-00A6-4D8E-88C0-929747B7FB67}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Video", "Azaion.Video\Azaion.Video.csproj", "{0FB51B6B-2C77-4F24-B640-FEEBC5395E33}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azaion.Repository", "Azaion.Repository\Azaion.Repository.csproj", "{9620B192-0B9F-4AA7-A6EE-64616FBE1B5F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -12,5 +16,13 @@ Global
{1D56907A-00A6-4D8E-88C0-929747B7FB67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D56907A-00A6-4D8E-88C0-929747B7FB67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D56907A-00A6-4D8E-88C0-929747B7FB67}.Release|Any CPU.Build.0 = Release|Any CPU
{0FB51B6B-2C77-4F24-B640-FEEBC5395E33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FB51B6B-2C77-4F24-B640-FEEBC5395E33}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FB51B6B-2C77-4F24-B640-FEEBC5395E33}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FB51B6B-2C77-4F24-B640-FEEBC5395E33}.Release|Any CPU.Build.0 = Release|Any CPU
{9620B192-0B9F-4AA7-A6EE-64616FBE1B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9620B192-0B9F-4AA7-A6EE-64616FBE1B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9620B192-0B9F-4AA7-A6EE-64616FBE1B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9620B192-0B9F-4AA7-A6EE-64616FBE1B5F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -11,4 +11,8 @@
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Azaion.Repository\Azaion.Repository.csproj" />
</ItemGroup>
</Project>
+7 -3
View File
@@ -1,13 +1,17 @@
using Azaion.Repository;
using Azaion.Repository.DTO;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.Configure<ConnectionStrings>(builder.Configuration.GetSection(nameof(ConnectionStrings)));
builder.Services.AddSingleton<IDbFactory, DbFactory>(sp => new DbFactory(sp.GetService<IOptions<ConnectionStrings>>()!.Value.FraudDb!));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();