diff --git a/AyCode.Core.Tests/AyCode.Core.Tests.csproj b/AyCode.Core.Tests/AyCode.Core.Tests.csproj
new file mode 100644
index 0000000..b8cb93d
--- /dev/null
+++ b/AyCode.Core.Tests/AyCode.Core.Tests.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/AyCode.Core.Tests/GlobalUsings.cs b/AyCode.Core.Tests/GlobalUsings.cs
new file mode 100644
index 0000000..ab67c7e
--- /dev/null
+++ b/AyCode.Core.Tests/GlobalUsings.cs
@@ -0,0 +1 @@
+global using Microsoft.VisualStudio.TestTools.UnitTesting;
\ No newline at end of file
diff --git a/AyCode.Core.Tests/TestModelBase.cs b/AyCode.Core.Tests/TestModelBase.cs
new file mode 100644
index 0000000..f863edb
--- /dev/null
+++ b/AyCode.Core.Tests/TestModelBase.cs
@@ -0,0 +1,9 @@
+namespace AyCode.Core.Tests;
+
+public abstract class TestModelBase
+{
+ protected TestModelBase()
+ {
+ //if (IsProductVersion) throw new Exception("IsProductVersion!!!!!");
+ }
+}
\ No newline at end of file
diff --git a/AyCode.Core.sln b/AyCode.Core.sln
index 16fe191..fb25098 100644
--- a/AyCode.Core.sln
+++ b/AyCode.Core.sln
@@ -3,23 +3,27 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34221.43
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Core", "AyCode.Core\AyCode.Core.csproj", "{8CCC4969-7306-4747-8A58-80AC5A062EE1}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Core", "AyCode.Core\AyCode.Core.csproj", "{8CCC4969-7306-4747-8A58-80AC5A062EE1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Entities", "AyCode.Entities\AyCode.Entities.csproj", "{A2105535-1397-4307-B61B-E49C983353B9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Entities", "AyCode.Entities\AyCode.Entities.csproj", "{A2105535-1397-4307-B61B-E49C983353B9}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Entities.Server", "AyCode.Entities.Server\AyCode.Entities.Server.csproj", "{FB027D80-8949-403B-9A86-8E99F305016E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Entities.Server", "AyCode.Entities.Server\AyCode.Entities.Server.csproj", "{FB027D80-8949-403B-9A86-8E99F305016E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Database", "AyCode.Database\AyCode.Database.csproj", "{CAB60420-9F66-42D9-B67E-8E837DBA1F30}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Database", "AyCode.Database\AyCode.Database.csproj", "{CAB60420-9F66-42D9-B67E-8E837DBA1F30}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Interfaces", "AyCode.Interfaces\AyCode.Interfaces.csproj", "{DC42F79D-EEF0-4F32-8608-230F24C6F22A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Interfaces", "AyCode.Interfaces\AyCode.Interfaces.csproj", "{DC42F79D-EEF0-4F32-8608-230F24C6F22A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Interfaces.Server", "AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj", "{0B5AC35E-3E71-42DC-B503-80D6D3089F91}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Interfaces.Server", "AyCode.Interfaces.Server\AyCode.Interfaces.Server.csproj", "{0B5AC35E-3E71-42DC-B503-80D6D3089F91}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Core.Server", "AyCode.Core.Server\AyCode.Core.Server.csproj", "{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Core.Server", "AyCode.Core.Server\AyCode.Core.Server.csproj", "{F8ECCA33-B5EA-490D-B1A1-D33B5E4238A5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Utils", "AyCode.Utils\AyCode.Utils.csproj", "{35D47907-CE4F-435B-823E-A02BE59C16D7}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Utils", "AyCode.Utils\AyCode.Utils.csproj", "{35D47907-CE4F-435B-823E-A02BE59C16D7}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Utils.Server", "AyCode.Utils.Server\AyCode.Utils.Server.csproj", "{EBC6371C-9454-473D-9547-DF9DECEB2D2A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Utils.Server", "AyCode.Utils.Server\AyCode.Utils.Server.csproj", "{EBC6371C-9454-473D-9547-DF9DECEB2D2A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Database.Tests", "AyCode.Database.Tests\AyCode.Database.Tests.csproj", "{15272F57-771E-47BE-A960-AD75935254D0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Core.Tests", "AyCode.Core.Tests\AyCode.Core.Tests.csproj", "{320A245F-6731-476D-A9D8-77888E6B5D9C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -63,6 +67,14 @@ Global
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBC6371C-9454-473D-9547-DF9DECEB2D2A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {15272F57-771E-47BE-A960-AD75935254D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {15272F57-771E-47BE-A960-AD75935254D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {15272F57-771E-47BE-A960-AD75935254D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {15272F57-771E-47BE-A960-AD75935254D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {320A245F-6731-476D-A9D8-77888E6B5D9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {320A245F-6731-476D-A9D8-77888E6B5D9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {320A245F-6731-476D-A9D8-77888E6B5D9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {320A245F-6731-476D-A9D8-77888E6B5D9C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/AyCode.Database.Tests/AyCode.Database.Tests.csproj b/AyCode.Database.Tests/AyCode.Database.Tests.csproj
new file mode 100644
index 0000000..f0fb1d1
--- /dev/null
+++ b/AyCode.Database.Tests/AyCode.Database.Tests.csproj
@@ -0,0 +1,30 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AyCode.Database.Tests/DatabaseTestModelBase.cs b/AyCode.Database.Tests/DatabaseTestModelBase.cs
new file mode 100644
index 0000000..9ad61b3
--- /dev/null
+++ b/AyCode.Database.Tests/DatabaseTestModelBase.cs
@@ -0,0 +1,12 @@
+using AyCode.Core.Tests;
+using AyCode.Database.DbContexts;
+
+namespace AyCode.Database.Tests;
+
+public abstract class DatabaseTestModelBase : TestModelBase where : DbContextBase
+{
+ protected DatabaseTestModelBase()
+ {
+ //var dal = new dal
+ }
+}
\ No newline at end of file
diff --git a/AyCode.Database.Tests/DatabaseTests.cs b/AyCode.Database.Tests/DatabaseTests.cs
new file mode 100644
index 0000000..f4ace3d
--- /dev/null
+++ b/AyCode.Database.Tests/DatabaseTests.cs
@@ -0,0 +1,11 @@
+namespace AyCode.Database.Tests
+{
+ [TestClass]
+ public abstract class DatabaseTests : DatabaseTestModelBase
+ {
+ [TestMethod]
+ public void TestMethod1()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/AyCode.Database.Tests/GlobalUsings.cs b/AyCode.Database.Tests/GlobalUsings.cs
new file mode 100644
index 0000000..ab67c7e
--- /dev/null
+++ b/AyCode.Database.Tests/GlobalUsings.cs
@@ -0,0 +1 @@
+global using Microsoft.VisualStudio.TestTools.UnitTesting;
\ No newline at end of file
diff --git a/AyCode.Database/DalBase.cs b/AyCode.Database/DalBase.cs
new file mode 100644
index 0000000..1f1d22a
--- /dev/null
+++ b/AyCode.Database/DalBase.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AyCode.Database.DbContexts;
+using AyCode.Utils.Extensions;
+
+namespace AyCode.Database;
+
+public class DalBase where TDbContext : DbContextBase
+{
+ public string Name { get; private set; }
+ private TDbContext _ctx;
+ public TDbContext Ctx => _ctx;
+
+ public DalBase() : this(Activator.CreateInstance())
+ { }
+
+ public DalBase(TDbContext ctx)
+ {
+ _ctx = ctx;
+
+ if (_ctx.Name.IsNullOrWhiteSpace())
+ _ctx.Name = _ctx.GetType().Name;
+
+ Name = $"{this.GetType().Name}, {_ctx.Name}";
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+}
\ No newline at end of file
diff --git a/AyCode.Database/DbContexts/DbContextBase.cs b/AyCode.Database/DbContexts/DbContextBase.cs
index 4a81766..d144087 100644
--- a/AyCode.Database/DbContexts/DbContextBase.cs
+++ b/AyCode.Database/DbContexts/DbContextBase.cs
@@ -1,4 +1,5 @@
-using Microsoft.EntityFrameworkCore;
+using System.Runtime.CompilerServices;
+using Microsoft.EntityFrameworkCore;
using AyCode.Database.Extensions;
using AyCode.Interfaces.TimeStampInfo;
@@ -10,12 +11,12 @@ public class DbContextBase : DbContext
public Guid SessionId { get; protected set; } = Guid.NewGuid();
- public DbContextBase() : this(string.Empty)
+ public DbContextBase()
{
//DbInterception.Add(new UtcDateTimeDbCommandInterceptor());
}
- public DbContextBase(string name) : base()
+ public DbContextBase(string name) : this()
{
Name = name;
}
diff --git a/AyCode.Entities.Server/AyCode.Entities.Server.csproj b/AyCode.Entities.Server/AyCode.Entities.Server.csproj
index cfadb03..012d8be 100644
--- a/AyCode.Entities.Server/AyCode.Entities.Server.csproj
+++ b/AyCode.Entities.Server/AyCode.Entities.Server.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/AyCode.Entities/AyCode.Entities.csproj b/AyCode.Entities/AyCode.Entities.csproj
index cfadb03..0117eb9 100644
--- a/AyCode.Entities/AyCode.Entities.csproj
+++ b/AyCode.Entities/AyCode.Entities.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/AyCode.Entities/Profiles/IProfileBase.cs b/AyCode.Entities/Profiles/IProfileBase.cs
new file mode 100644
index 0000000..0525668
--- /dev/null
+++ b/AyCode.Entities/Profiles/IProfileBase.cs
@@ -0,0 +1,10 @@
+using AyCode.Entities.Interfaces;
+using AyCode.Interfaces;
+using AyCode.Interfaces.TimeStampInfo;
+
+namespace AyCode.Entities.Profiles;
+
+public interface IProfileBase : IEntityGuid, IOwnerId, ITimeStampInfo
+{
+ Guid UserMediaId { get; set; }
+}
\ No newline at end of file
diff --git a/AyCode.Entities/Profiles/ProfileBase.cs b/AyCode.Entities/Profiles/ProfileBase.cs
new file mode 100644
index 0000000..34d9e2a
--- /dev/null
+++ b/AyCode.Entities/Profiles/ProfileBase.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AyCode.Entities.Profiles
+{
+ [Table("ProfileBase")]
+ public class ProfileBase : IProfileBase
+ {
+ public ProfileBase() { }
+ public ProfileBase(Guid ownerId) : this()
+ {
+ OwnerId = ownerId;
+ }
+
+ [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
+ public Guid Id { get; set; }
+ public Guid OwnerId { get; }
+ public Guid UserMediaId { get; set; }
+
+ public DateTime Created { get; set; }
+ public DateTime Modified { get; set; }
+ }
+}
diff --git a/AyCode.Entities/Users/IUserBase.cs b/AyCode.Entities/Users/IUserBase.cs
new file mode 100644
index 0000000..9940007
--- /dev/null
+++ b/AyCode.Entities/Users/IUserBase.cs
@@ -0,0 +1,10 @@
+using AyCode.Entities.Interfaces;
+using AyCode.Interfaces.TimeStampInfo;
+
+namespace AyCode.Entities.Users;
+
+public interface IUserBase : IEntityGuid, ITimeStampInfo
+{
+ string Email { get; }
+ string Password { get; }
+}
\ No newline at end of file
diff --git a/AyCode.Entities/Users/UserBase.cs b/AyCode.Entities/Users/UserBase.cs
new file mode 100644
index 0000000..f413f3b
--- /dev/null
+++ b/AyCode.Entities/Users/UserBase.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AyCode.Entities.Users
+{
+ [Table("ProfileBase")]
+ public class UserBase : IUserBase
+ {
+ public UserBase() { }
+ public UserBase(string email, string password) : this(Guid.NewGuid(), email, password) { }
+ public UserBase(Guid id, string email, string password) : this()
+ {
+ Id = id;
+ Email = email;
+ Password = password;
+ }
+
+ [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
+ public Guid Id { get; set; }
+ public string Email { get; }
+ public string Password { get; }
+
+ public DateTime Created { get; set; }
+ public DateTime Modified { get; set; }
+ }
+}
diff --git a/AyCode.Interfaces/IOwnerId.cs b/AyCode.Interfaces/IOwnerId.cs
new file mode 100644
index 0000000..12b7540
--- /dev/null
+++ b/AyCode.Interfaces/IOwnerId.cs
@@ -0,0 +1,6 @@
+namespace AyCode.Interfaces;
+
+public interface IOwnerId
+{
+ Guid OwnerId { get; }
+}
diff --git a/AyCode.Utils/AyCode.Utils.csproj b/AyCode.Utils/AyCode.Utils.csproj
index cfadb03..9413cb8 100644
--- a/AyCode.Utils/AyCode.Utils.csproj
+++ b/AyCode.Utils/AyCode.Utils.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/AyCode.Utils/Extensions/DateTimeExtension.cs b/AyCode.Utils/Extensions/DateTimeExtension.cs
new file mode 100644
index 0000000..fa6b5c9
--- /dev/null
+++ b/AyCode.Utils/Extensions/DateTimeExtension.cs
@@ -0,0 +1,20 @@
+using JetBrains.Annotations;
+
+namespace AyCode.Utils.Extensions
+{
+ public static class DateTimeExtension
+ {
+ public static bool IsNullOrEmpty(this DateTime dateTime) => dateTime == DateTime.MinValue;
+
+ [ContractAnnotation("dateTime:null => true; dateTime:notnull <= false")]
+ public static bool IsNullOrEmpty(this DateTime? dateTime) => dateTime == null || dateTime == DateTime.MinValue;
+
+ public static bool IsEqualSqlDateTime2(this DateTime dtSource, DateTime dateTime)
+ {
+ return dtSource == dateTime ||
+ (dtSource.Kind == dateTime.Kind &&
+ dtSource.Millisecond == dateTime.Millisecond && dtSource.Hour == dateTime.Hour && dtSource.Second == dateTime.Second && dtSource.Minute == dateTime.Minute &&
+ dtSource.Day == dateTime.Day && dtSource.Month == dateTime.Month && dtSource.Year == dateTime.Year);
+ }
+ }
+}
diff --git a/AyCode.Utils/Extensions/GuidExtensions.cs b/AyCode.Utils/Extensions/GuidExtensions.cs
new file mode 100644
index 0000000..94fb475
--- /dev/null
+++ b/AyCode.Utils/Extensions/GuidExtensions.cs
@@ -0,0 +1,15 @@
+using JetBrains.Annotations;
+
+namespace AyCode.Utils.Extensions
+{
+ public static class GuidExtensions
+ {
+ //[ContractAnnotation("=> true, result: notnull; => false, result: null")]
+ //[ContractAnnotation("true => null; false => notnull")]
+ public static bool IsNullOrEmpty(this Guid guid) => guid == Guid.Empty;
+
+ //[ContractAnnotation("=> true, result: notnull; => false, result: null")]
+ [ContractAnnotation("guid:null => true; guid:notnull <= false")]
+ public static bool IsNullOrEmpty(this Guid? guid) => guid == null || guid == Guid.Empty;
+ }
+}
diff --git a/AyCode.Utils/Extensions/LockExtensions.cs b/AyCode.Utils/Extensions/LockExtensions.cs
new file mode 100644
index 0000000..5a2859a
--- /dev/null
+++ b/AyCode.Utils/Extensions/LockExtensions.cs
@@ -0,0 +1,28 @@
+using AyCode.Utils.Wrappers;
+
+namespace AyCode.Utils.Extensions
+{
+ public static class LockExtensions
+ {
+ public static IDisposable UseWaitOne(this Mutex mutex)
+ {
+ mutex.WaitOne();
+
+ return new ReleaseWrapperMutex(mutex);
+ }
+
+ public static IDisposable UseWait(this SemaphoreSlim semaphore, CancellationToken cancelToken = default)
+ {
+ semaphore.Wait(cancelToken);
+
+ return new ReleaseWrapperSemaphore(semaphore);
+ }
+
+ public static async Task UseWaitAsync(this SemaphoreSlim semaphore, CancellationToken cancelToken = default)
+ {
+ await semaphore.WaitAsync(cancelToken).ConfigureAwait(false);
+
+ return new ReleaseWrapperSemaphore(semaphore);
+ }
+ }
+}
diff --git a/AyCode.Utils/Extensions/StringExtensions.cs b/AyCode.Utils/Extensions/StringExtensions.cs
new file mode 100644
index 0000000..48c0174
--- /dev/null
+++ b/AyCode.Utils/Extensions/StringExtensions.cs
@@ -0,0 +1,40 @@
+using System.Diagnostics.CodeAnalysis;
+using JetBrains.Annotations;
+
+namespace AyCode.Utils.Extensions
+{
+ public static class StringExtensions
+ {
+ //[ContractAnnotation("str:null => true; str:notnull <= false")]
+ [ContractAnnotation("str:null => true; str:notnull <= false")]
+ public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] this string str) => str == null || str.Length == 0;
+
+ [ContractAnnotation("str:null => true;")]
+ public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)] this string str)
+ {
+ if (str == null || str.Length == 0) return true;
+ if (!char.IsWhiteSpace(str[0])) return false;
+
+ for (var i = 1; i < str.Length; i++)
+ {
+ if (!char.IsWhiteSpace(str[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ public static string FirstLetterToUpper(string str)
+ {
+ if (str.IsNullOrWhiteSpace())
+ return str;
+
+ if (str.Length == 1)
+ return str.ToUpper();
+
+ str = str.ToLower();
+
+ return char.ToUpper(str[0]) + str[1..];
+ }
+ }
+}
diff --git a/AyCode.Utils/Wrappers/ReleaseWrapperMutex.cs b/AyCode.Utils/Wrappers/ReleaseWrapperMutex.cs
new file mode 100644
index 0000000..008134a
--- /dev/null
+++ b/AyCode.Utils/Wrappers/ReleaseWrapperMutex.cs
@@ -0,0 +1,19 @@
+namespace AyCode.Utils.Wrappers
+{
+ public class ReleaseWrapperMutex : IDisposable
+ {
+ private readonly Mutex _mutex;
+ private bool _isDisposed;
+
+ public ReleaseWrapperMutex(Mutex mutex) => _mutex = mutex;
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ _mutex.ReleaseMutex();
+ _isDisposed = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/AyCode.Utils/Wrappers/ReleaseWrapperSemaphore.cs b/AyCode.Utils/Wrappers/ReleaseWrapperSemaphore.cs
new file mode 100644
index 0000000..229f368
--- /dev/null
+++ b/AyCode.Utils/Wrappers/ReleaseWrapperSemaphore.cs
@@ -0,0 +1,19 @@
+namespace AyCode.Utils.Wrappers
+{
+ public class ReleaseWrapperSemaphore : IDisposable
+ {
+ private readonly SemaphoreSlim _semaphore;
+ private bool _isDisposed;
+
+ public ReleaseWrapperSemaphore(SemaphoreSlim semaphore) => _semaphore = semaphore;
+
+ public void Dispose()
+ {
+ if (_isDisposed)
+ return;
+
+ _semaphore.Release();
+ _isDisposed = true;
+ }
+ }
+}
\ No newline at end of file