Infrastructure
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Vizhvizh.BuildingBlocks.Domain;
|
||||
|
||||
public class BaseEntityConfiguration<T, TId, TIdType> : IEntityTypeConfiguration<T>
|
||||
where T : Entity<TId>
|
||||
where TId : TypedIdValueBase<TIdType>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<T> builder)
|
||||
{
|
||||
// تنظیمات Id
|
||||
ConfigureId(builder);
|
||||
|
||||
// تنظیمات RowVersion
|
||||
ConfigureRowVersion(builder);
|
||||
|
||||
// تنظیمات CreateOn (اگر وجود داشته باشد)
|
||||
ConfigureCreateOn(builder);
|
||||
}
|
||||
|
||||
private void ConfigureId(EntityTypeBuilder<T> builder)
|
||||
{
|
||||
builder.HasKey(x => x.Id);
|
||||
|
||||
if (typeof(TIdType) == typeof(int) || typeof(TIdType) == typeof(long))
|
||||
{
|
||||
// ❌ مشکل: اینجا نمیتوانیم به نام جدول دسترسی داشته باشیم
|
||||
// builder.UseHiLo($"Sequence_{typeof(T).Name}")
|
||||
|
||||
// ✅ راهحل: در اینجا فقط تنظیمات Id را انجام بده، Hi-Lo را بعداً اعمال کن
|
||||
builder.Property(x => x.Id)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => (TId)Activator.CreateInstance(typeof(TId), value)!)
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
// ❌ UseHiLo را اینجا نزنید، چون هنوز نام جدول مشخص نیست
|
||||
}
|
||||
else if (typeof(TIdType) == typeof(Guid))
|
||||
{
|
||||
builder.Property(x => x.Id)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => (TId)Activator.CreateInstance(typeof(TId), value)!)
|
||||
.HasDefaultValueSql("NEWSEQUENTIALID()")
|
||||
.ValueGeneratedOnAdd();
|
||||
}
|
||||
else if (typeof(TIdType) == typeof(string))
|
||||
{
|
||||
builder.Property(x => x.Id)
|
||||
.HasConversion(
|
||||
id => id.Value,
|
||||
value => (TId)Activator.CreateInstance(typeof(TId), value)!)
|
||||
.HasMaxLength(50);
|
||||
}
|
||||
}
|
||||
private void ConfigureRowVersion(EntityTypeBuilder<T> builder)
|
||||
{
|
||||
// بررسی وجود خاصیت RowVersion با Reflection
|
||||
var hasRowVersion = typeof(T).GetProperty("RowVersion") != null;
|
||||
|
||||
if (hasRowVersion)
|
||||
{
|
||||
// تنظیم RowVersion به عنوان Concurrency Token
|
||||
builder.Property<byte[]>("RowVersion")
|
||||
.IsRowVersion() // این یک خط همه کارها را میکند
|
||||
.IsConcurrencyToken()
|
||||
.ValueGeneratedOnAddOrUpdate();
|
||||
|
||||
// برای دیتابیسهای مختلف:
|
||||
// builder.Property<byte[]>("RowVersion").HasDefaultValueSql("rowversion");
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureCreateOn(EntityTypeBuilder<T> builder)
|
||||
{
|
||||
// تنظیم CreateOn (اگر وجود داشته باشد)
|
||||
var hasCreateOn = typeof(T).GetProperty("CreateOn") != null;
|
||||
|
||||
if (hasCreateOn)
|
||||
{
|
||||
builder.Property<DateTime>("CreateOn")
|
||||
.HasDefaultValueSql("GETDATE()") // SQL Server
|
||||
// برای PostgreSQL: .HasDefaultValueSql("CURRENT_TIMESTAMP")
|
||||
// برای MySQL: .HasDefaultValueSql("CURRENT_TIMESTAMP")
|
||||
.ValueGeneratedOnAdd();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Vizhvizh.BuildingBlocks.Infrastructure.Lifetimes;
|
||||
|
||||
public interface IScopeDependency
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Vizhvizh.BuildingBlocks.Infrastructure.Lifetimes;
|
||||
|
||||
public interface ISingletonDependency
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Vizhvizh.BuildingBlocks.Infrastructure.Lifetimes;
|
||||
|
||||
public interface ITransientDependency
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Vizhvizh.BuildingBlocks.Domain;
|
||||
|
||||
public static class ModelBuilderExtensions
|
||||
{
|
||||
public static void AddHiLoSequences(this ModelBuilder modelBuilder)
|
||||
{
|
||||
var entityTypes = modelBuilder.Model.GetEntityTypes();
|
||||
|
||||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
var primaryKey = entityType.FindPrimaryKey();
|
||||
if (primaryKey == null) continue;
|
||||
|
||||
var keyProperty = primaryKey.Properties.FirstOrDefault();
|
||||
if (keyProperty == null) continue;
|
||||
|
||||
// ✅ استخراج نوع واقعی از TypedIdValueBase
|
||||
var actualKeyType = GetUnderlyingKeyType(keyProperty.ClrType);
|
||||
|
||||
// فقط برای int و long
|
||||
if (actualKeyType == typeof(int) || actualKeyType == typeof(long))
|
||||
{
|
||||
var tableName = entityType.GetTableName();
|
||||
var sequenceName = GetSequenceName(tableName ?? entityType.Name);
|
||||
var schema = entityType.GetSchema();
|
||||
|
||||
if (actualKeyType == typeof(int))
|
||||
{
|
||||
modelBuilder.HasSequence<int>(sequenceName, schema)
|
||||
.StartsAt(1)
|
||||
.IncrementsBy(1);
|
||||
}
|
||||
else if (actualKeyType == typeof(long))
|
||||
{
|
||||
modelBuilder.HasSequence<long>(sequenceName, schema)
|
||||
.StartsAt(1)
|
||||
.IncrementsBy(1);
|
||||
}
|
||||
|
||||
keyProperty.SetHiLoSequenceName(sequenceName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//public static void UseHiLoForEntities(this ModelBuilder modelBuilder)
|
||||
//{
|
||||
// var entityTypes = modelBuilder.Model.GetEntityTypes();
|
||||
|
||||
// foreach (var entityType in entityTypes)
|
||||
// {
|
||||
// var primaryKey = entityType.FindPrimaryKey();
|
||||
// if (primaryKey == null) continue;
|
||||
|
||||
// var keyProperty = primaryKey.Properties.FirstOrDefault();
|
||||
// if (keyProperty == null) continue;
|
||||
|
||||
// // ✅ از همان متد استفاده کنید
|
||||
// var actualKeyType = GetUnderlyingKeyType(keyProperty.ClrType);
|
||||
|
||||
// if (actualKeyType == typeof(int) || actualKeyType == typeof(long))
|
||||
// {
|
||||
// var tableName = entityType.GetTableName();
|
||||
// var sequenceName = GetSequenceName(tableName ?? entityType.Name);
|
||||
|
||||
// // تنظیم Hi-Lo روی Property
|
||||
// keyProperty.SetHiLoSequenceName(sequenceName);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// استخراج نوع اصلی از TypedIdValueBase
|
||||
/// پشتیبانی از:
|
||||
/// - TypedIdValueBase<int>
|
||||
/// - TypedIdValueBase<long>
|
||||
/// - CategoryId : TypedIdValueBase<long>
|
||||
/// </summary>
|
||||
private static Type GetUnderlyingKeyType(Type keyType)
|
||||
{
|
||||
// حالت 1: خود keyType از نوع TypedIdValueBase<T> باشد
|
||||
if (keyType.IsGenericType &&
|
||||
keyType.GetGenericTypeDefinition() == typeof(TypedIdValueBase<>))
|
||||
{
|
||||
return keyType.GetGenericArguments()[0];
|
||||
}
|
||||
|
||||
// حالت 2: keyType از TypedIdValueBase<T> ارثبری کرده باشد
|
||||
var baseType = keyType.BaseType;
|
||||
while (baseType != null && baseType != typeof(object))
|
||||
{
|
||||
if (baseType.IsGenericType &&
|
||||
baseType.GetGenericTypeDefinition() == typeof(TypedIdValueBase<>))
|
||||
{
|
||||
return baseType.GetGenericArguments()[0];
|
||||
}
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
|
||||
// حالت 3: خود keyType int یا long باشد
|
||||
if (keyType == typeof(int) || keyType == typeof(long) ||
|
||||
keyType == typeof(int?) || keyType == typeof(long?))
|
||||
{
|
||||
return Nullable.GetUnderlyingType(keyType) ?? keyType;
|
||||
}
|
||||
|
||||
// حالت 4: نوع دیگر (مثلاً Guid, string)
|
||||
return keyType;
|
||||
}
|
||||
|
||||
private static string GetSequenceName(string tableName)
|
||||
{
|
||||
return $"Sequence_{tableName}";
|
||||
}
|
||||
}
|
||||
+1
-8
@@ -6,14 +6,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.25" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.25" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.25" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Scrutor" Version="6.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VichVich.BuildingBlocks.Application\Vizhvizh.BuildingBlocks.Application.csproj" />
|
||||
|
||||
Reference in New Issue
Block a user