DapperTransaction güncellemesi
Hatalar vermeye başladı. Listelerdeki veriler yüklenmeden yeni butonuna basınca hata aldım.
This commit is contained in:
parent
5e8ca56af1
commit
01db1c6b23
13 changed files with 513 additions and 291 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;",
|
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;",
|
||||||
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;",
|
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;",
|
||||||
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"Seed": false,
|
"Seed": false,
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"SqlServer": "Server=localhost;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;",
|
"SqlServer": "Server=localhost;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;",
|
||||||
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=localhost;Port=5432;Database=Erp;"
|
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=localhost;Port=5432;Database=Erp;"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Data;
|
using System;
|
||||||
|
using System.Data;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -25,43 +26,24 @@ public class DapperTransactionApi : ITransactionApi, ISupportsRollback
|
||||||
|
|
||||||
public async Task CommitAsync(CancellationToken cancellationToken = default)
|
public async Task CommitAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
// Check if transaction is still active
|
|
||||||
if (_isCompleted)
|
if (_isCompleted)
|
||||||
{
|
{
|
||||||
return; // Already completed, nothing to do
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if connection is still open and transaction is not disposed
|
|
||||||
if (DbTransaction?.Connection == null || DbTransaction.Connection.State != ConnectionState.Open)
|
if (DbTransaction?.Connection == null || DbTransaction.Connection.State != ConnectionState.Open)
|
||||||
{
|
{
|
||||||
_isCompleted = true;
|
_isCompleted = true;
|
||||||
return; // Connection closed or transaction disposed
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await DbTransaction.CommitAsync(CancellationTokenProvider.FallbackToProvider(cancellationToken));
|
await DbTransaction.CommitAsync(CancellationTokenProvider.FallbackToProvider(cancellationToken));
|
||||||
_isCompleted = true;
|
|
||||||
}
|
}
|
||||||
catch (System.InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
{
|
{
|
||||||
// Transaction already completed or disposed
|
// Transaction already completed or disposed
|
||||||
_isCompleted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!_isCompleted && DbTransaction?.Connection != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// If not completed, rollback before disposing
|
|
||||||
DbTransaction?.Rollback();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore rollback errors during disposal
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
@ -69,33 +51,51 @@ public class DapperTransactionApi : ITransactionApi, ISupportsRollback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DbTransaction?.Dispose();
|
public async Task RollbackAsync(CancellationToken cancellationToken = default)
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RollbackAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
// Check if transaction is still active
|
|
||||||
if (_isCompleted)
|
if (_isCompleted)
|
||||||
{
|
{
|
||||||
return; // Already completed, nothing to do
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if connection is still open and transaction is not disposed
|
|
||||||
if (DbTransaction?.Connection == null || DbTransaction.Connection.State != ConnectionState.Open)
|
if (DbTransaction?.Connection == null || DbTransaction.Connection.State != ConnectionState.Open)
|
||||||
{
|
{
|
||||||
_isCompleted = true;
|
_isCompleted = true;
|
||||||
return; // Connection closed or transaction disposed
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await DbTransaction.RollbackAsync(CancellationTokenProvider.FallbackToProvider(cancellationToken));
|
await DbTransaction.RollbackAsync(CancellationTokenProvider.FallbackToProvider(cancellationToken));
|
||||||
_isCompleted = true;
|
|
||||||
}
|
}
|
||||||
catch (System.InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
{
|
{
|
||||||
// Transaction already completed or disposed
|
// Transaction already completed or disposed
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
_isCompleted = true;
|
_isCompleted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_isCompleted && DbTransaction?.Connection?.State == ConnectionState.Open)
|
||||||
|
{
|
||||||
|
// UoW commit/rollback çağırmadıysa, dispose sırasında rollback dene
|
||||||
|
DbTransaction.Rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Rollback sırasında hata olursa yut
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isCompleted = true;
|
||||||
|
DbTransaction?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,118 +15,55 @@ namespace Kurs.Platform.Domain.DynamicData;
|
||||||
[ExposeKeyedService<IDynamicDataRepository>("Ms")]
|
[ExposeKeyedService<IDynamicDataRepository>("Ms")]
|
||||||
public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency, IUnitOfWorkEnabled, IDisposable
|
public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency, IUnitOfWorkEnabled, IDisposable
|
||||||
{
|
{
|
||||||
private readonly IUnitOfWorkManager unitOfWorkManager;
|
private readonly IUnitOfWorkManager _unitOfWorkManager;
|
||||||
private readonly ICancellationTokenProvider cancellationTokenProvider;
|
private readonly ICancellationTokenProvider _cancellationTokenProvider;
|
||||||
private readonly Dictionary<string, DbTransaction> transactions;
|
|
||||||
private readonly Dictionary<string, SqlConnection> connections;
|
private readonly Dictionary<string, DbTransaction> _transactions;
|
||||||
private readonly HashSet<string> registeredTransactions; // Track registered transactions
|
private readonly Dictionary<string, SqlConnection> _connections;
|
||||||
|
private readonly HashSet<string> _registeredTransactions;
|
||||||
|
private readonly HashSet<string> _registeredConnections;
|
||||||
private readonly object _lock = new object();
|
private readonly object _lock = new object();
|
||||||
|
|
||||||
public bool IsDisposed { get; private set; }
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
public MsDynamicDataRepository(
|
public MsDynamicDataRepository(
|
||||||
IUnitOfWorkManager unitOfWorkManager,
|
IUnitOfWorkManager unitOfWorkManager,
|
||||||
ICancellationTokenProvider cancellationTokenProvider)
|
ICancellationTokenProvider cancellationTokenProvider)
|
||||||
{
|
{
|
||||||
this.unitOfWorkManager = unitOfWorkManager;
|
_unitOfWorkManager = unitOfWorkManager;
|
||||||
this.cancellationTokenProvider = cancellationTokenProvider;
|
_cancellationTokenProvider = cancellationTokenProvider;
|
||||||
transactions = new Dictionary<string, DbTransaction>();
|
|
||||||
connections = new Dictionary<string, SqlConnection>();
|
_transactions = [];
|
||||||
registeredTransactions = new HashSet<string>();
|
_connections = [];
|
||||||
|
_registeredTransactions = [];
|
||||||
|
_registeredConnections = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<DbTransaction> GetOrCreateTransactionAsync(SqlConnection con)
|
private string BuildKey(string cs)
|
||||||
{
|
{
|
||||||
var key = $"Dapper_{con.ConnectionString}";
|
var uowId = _unitOfWorkManager.Current?.GetHashCode() ?? 0;
|
||||||
|
return $"Dapper_{uowId}_{cs}";
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
// Check if we have a valid transaction for this connection
|
|
||||||
if (transactions.TryGetValue(key, out var transaction))
|
|
||||||
{
|
|
||||||
// Validate transaction is still usable
|
|
||||||
if (transaction?.Connection != null &&
|
|
||||||
transaction.Connection == con &&
|
|
||||||
transaction.Connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalid transaction, remove it
|
|
||||||
try { transaction?.Dispose(); } catch { }
|
|
||||||
transactions.Remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure connection is open
|
|
||||||
if (con.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await con.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new transaction
|
|
||||||
var newTransaction = await con.BeginTransactionAsync();
|
|
||||||
bool shouldRegister = false;
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
transactions[key] = newTransaction;
|
|
||||||
|
|
||||||
// Only register with UnitOfWork once per transaction key
|
|
||||||
if (!registeredTransactions.Contains(key))
|
|
||||||
{
|
|
||||||
registeredTransactions.Add(key);
|
|
||||||
shouldRegister = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register with UnitOfWork if available and not already registered
|
|
||||||
if (shouldRegister && unitOfWorkManager.Current != null)
|
|
||||||
{
|
|
||||||
unitOfWorkManager.Current.AddTransactionApi(key, new DapperTransactionApi(newTransaction, cancellationTokenProvider));
|
|
||||||
|
|
||||||
unitOfWorkManager.Current.OnCompleted(() =>
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
transactions.Remove(key);
|
|
||||||
registeredTransactions.Remove(key);
|
|
||||||
}
|
|
||||||
return Task.CompletedTask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return newTransaction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<SqlConnection> GetOrCreateConnectionAsync(string cs)
|
private async Task<SqlConnection> GetOrCreateConnectionAsync(string cs)
|
||||||
{
|
{
|
||||||
|
var key = BuildKey(cs);
|
||||||
SqlConnection connection;
|
SqlConnection connection;
|
||||||
var key = $"Dapper_{cs}";
|
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
// Check if we have an existing connection
|
if (_connections.TryGetValue(key, out connection))
|
||||||
if (connections.TryGetValue(key, out connection))
|
|
||||||
{
|
{
|
||||||
// Connection exists, check its state
|
// varsa aynı connection'ı kullan
|
||||||
if (connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connection is not open, will handle outside lock
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create new connection
|
|
||||||
connection = new SqlConnection(cs);
|
connection = new SqlConnection(cs);
|
||||||
connections[key] = connection;
|
_connections[key] = connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle connection state outside of lock
|
// Lock dışında state yönetimi
|
||||||
try
|
|
||||||
{
|
|
||||||
if (connection.State == ConnectionState.Broken)
|
if (connection.State == ConnectionState.Broken)
|
||||||
{
|
{
|
||||||
connection.Close();
|
connection.Close();
|
||||||
|
|
@ -134,37 +71,29 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
|
|
||||||
if (connection.State == ConnectionState.Closed)
|
if (connection.State == ConnectionState.Closed)
|
||||||
{
|
{
|
||||||
await connection.OpenAsync();
|
await connection.OpenAsync(_cancellationTokenProvider.FallbackToProvider(default));
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// If connection failed, create a new one
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
connections.Remove(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connection = new SqlConnection(cs);
|
// UoW tamamlandığında connection'ı kapatmak için tek seferlik kayıt
|
||||||
|
if (_unitOfWorkManager.Current != null)
|
||||||
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
connections[key] = connection;
|
if (!_registeredConnections.Contains(key))
|
||||||
}
|
|
||||||
await connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register cleanup on UnitOfWork completion (only once)
|
|
||||||
if (unitOfWorkManager.Current != null)
|
|
||||||
{
|
{
|
||||||
unitOfWorkManager.Current.OnCompleted(async () =>
|
_registeredConnections.Add(key);
|
||||||
|
|
||||||
|
_unitOfWorkManager.Current.OnCompleted(async () =>
|
||||||
{
|
{
|
||||||
SqlConnection conn = null;
|
SqlConnection conn = null;
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (connections.TryGetValue(key, out conn))
|
if (_connections.TryGetValue(key, out conn))
|
||||||
{
|
{
|
||||||
connections.Remove(key);
|
_connections.Remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_registeredConnections.Remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn != null)
|
if (conn != null)
|
||||||
|
|
@ -177,27 +106,92 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
}
|
}
|
||||||
conn.Dispose();
|
conn.Dispose();
|
||||||
}
|
}
|
||||||
catch { }
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<DbTransaction> GetOrCreateTransactionAsync(SqlConnection con, string cs)
|
||||||
|
{
|
||||||
|
var key = BuildKey(cs);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_transactions.TryGetValue(key, out var existing))
|
||||||
|
{
|
||||||
|
if (existing?.Connection != null &&
|
||||||
|
existing.Connection == con &&
|
||||||
|
existing.Connection.State == ConnectionState.Open)
|
||||||
|
{
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { existing?.Dispose(); } catch { }
|
||||||
|
_transactions.Remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newTransaction = await con.BeginTransactionAsync(_cancellationTokenProvider.FallbackToProvider(default));
|
||||||
|
bool shouldRegister = false;
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_transactions[key] = newTransaction;
|
||||||
|
|
||||||
|
if (!_registeredTransactions.Contains(key))
|
||||||
|
{
|
||||||
|
_registeredTransactions.Add(key);
|
||||||
|
shouldRegister = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldRegister && _unitOfWorkManager.Current != null)
|
||||||
|
{
|
||||||
|
_unitOfWorkManager.Current.AddTransactionApi(
|
||||||
|
key,
|
||||||
|
new DapperTransactionApi(newTransaction, _cancellationTokenProvider)
|
||||||
|
);
|
||||||
|
|
||||||
|
_unitOfWorkManager.Current.OnCompleted(() =>
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_transactions.Remove(key);
|
||||||
|
_registeredTransactions.Remove(key);
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Dapper metotları ------------------
|
||||||
|
|
||||||
public virtual async Task<List<T>> QueryAsync<T>(string sql, string cs, Dictionary<string, object> parameters = null)
|
public virtual async Task<List<T>> QueryAsync<T>(string sql, string cs, Dictionary<string, object> parameters = null)
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
return (await dbConnection.QueryAsync<T>(sql, param, transaction)).AsList();
|
|
||||||
|
var result = await dbConnection.QueryAsync<T>(sql, param, transaction);
|
||||||
|
return result.AsList(); // buffered => reader kapanır, MARS gerekmez
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<IEnumerable<dynamic>> QueryAsync(string sql, string cs, Dictionary<string, object> parameters = null)
|
public virtual async Task<IEnumerable<dynamic>> QueryAsync(string sql, string cs, Dictionary<string, object> parameters = null)
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.QueryAsync(sql, param, transaction);
|
return await dbConnection.QueryAsync(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +199,8 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.QuerySingleAsync<T>(sql, param, transaction);
|
return await dbConnection.QuerySingleAsync<T>(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,25 +208,30 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.ExecuteScalarAsync<T>(sql, param, transaction);
|
return await dbConnection.ExecuteScalarAsync<T>(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<T> GetSingleField<T>(string cs, string tableName, string id, string selectFieldName, string idFieldName = "Id")
|
public virtual async Task<T> GetSingleField<T>(string cs, string tableName, string id, string selectFieldName, string idFieldName = "Id")
|
||||||
{
|
{
|
||||||
var param = new { ID = id };
|
var param = new { ID = id };
|
||||||
string sql = $"select {selectFieldName} from {tableName} where {idFieldName} = @ID ";
|
var sql = $"select {selectFieldName} from {tableName} where {idFieldName} = @ID ";
|
||||||
|
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.QueryFirstAsync<T>(sql, param, transaction);
|
return await dbConnection.QueryFirstAsync<T>(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> UpdateField(string cs, string tableName, string id, string updateFieldName, string value, string idFieldName = "Id")
|
public virtual async Task<int> UpdateField(string cs, string tableName, string id, string updateFieldName, string value, string idFieldName = "Id")
|
||||||
{
|
{
|
||||||
var param = new { ID = id };
|
var param = new { ID = id };
|
||||||
string sql = $"update {tableName} set {updateFieldName} = '{value}' where Id = @ID ";
|
var sql = $"update {tableName} set {updateFieldName} = '{value}' where {idFieldName} = @ID ";
|
||||||
|
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,10 +239,13 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------ Dispose ------------------
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
|
|
@ -251,49 +254,42 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (IsDisposed)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
// Dispose transactions first
|
foreach (var tx in _transactions.Values)
|
||||||
foreach (var transaction in transactions.Values)
|
|
||||||
{
|
{
|
||||||
try
|
try { tx?.Dispose(); } catch { }
|
||||||
{
|
|
||||||
transaction?.Dispose();
|
|
||||||
}
|
}
|
||||||
catch
|
_transactions.Clear();
|
||||||
{
|
_registeredTransactions.Clear();
|
||||||
// Ignore disposal errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transactions.Clear();
|
|
||||||
|
|
||||||
// Then dispose connections
|
foreach (var conn in _connections.Values)
|
||||||
foreach (var connection in connections.Values)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (connection != null)
|
if (conn != null)
|
||||||
{
|
{
|
||||||
if (connection.State == ConnectionState.Open)
|
if (conn.State != ConnectionState.Closed)
|
||||||
{
|
{
|
||||||
connection.Close();
|
conn.Close();
|
||||||
}
|
}
|
||||||
connection.Dispose();
|
conn.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch { }
|
||||||
{
|
}
|
||||||
// Ignore disposal errors
|
_connections.Clear();
|
||||||
}
|
_registeredConnections.Clear();
|
||||||
}
|
|
||||||
connections.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -15,69 +15,130 @@ namespace Kurs.Platform.Domain.DynamicData;
|
||||||
[ExposeKeyedService<IDynamicDataRepository>("Pg")]
|
[ExposeKeyedService<IDynamicDataRepository>("Pg")]
|
||||||
public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency, IUnitOfWorkEnabled, IDisposable
|
public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency, IUnitOfWorkEnabled, IDisposable
|
||||||
{
|
{
|
||||||
private readonly IUnitOfWorkManager unitOfWorkManager;
|
private readonly IUnitOfWorkManager _unitOfWorkManager;
|
||||||
private readonly ICancellationTokenProvider cancellationTokenProvider;
|
private readonly ICancellationTokenProvider _cancellationTokenProvider;
|
||||||
private Dictionary<string, DbTransaction> transactions;
|
|
||||||
private Dictionary<string, NpgsqlConnection> connections;
|
private readonly Dictionary<string, DbTransaction> _transactions;
|
||||||
|
private readonly Dictionary<string, NpgsqlConnection> _connections;
|
||||||
public bool IsDisposed { get; private set; }
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
public PgDynamicDataRepository(
|
public PgDynamicDataRepository(
|
||||||
IUnitOfWorkManager unitOfWorkManager,
|
IUnitOfWorkManager unitOfWorkManager,
|
||||||
ICancellationTokenProvider cancellationTokenProvider)
|
ICancellationTokenProvider cancellationTokenProvider)
|
||||||
{
|
{
|
||||||
this.unitOfWorkManager = unitOfWorkManager;
|
_unitOfWorkManager = unitOfWorkManager;
|
||||||
this.cancellationTokenProvider = cancellationTokenProvider;
|
_cancellationTokenProvider = cancellationTokenProvider;
|
||||||
transactions = [];
|
_transactions = [];
|
||||||
connections = [];
|
_connections = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<DbTransaction> GetOrCreateTransactionAsync(NpgsqlConnection con)
|
private string BuildKey(string cs)
|
||||||
{
|
{
|
||||||
var key = $"Dapper_{con.ConnectionString}";
|
var uowId = _unitOfWorkManager.Current?.GetHashCode() ?? 0;
|
||||||
var transaction = transactions.GetOrDefault(key);
|
return $"Dapper_{uowId}_{cs}";
|
||||||
if (transaction == null || transaction.Connection == null)
|
|
||||||
{
|
|
||||||
transaction = await con.BeginTransactionAsync();
|
|
||||||
unitOfWorkManager.Current.AddTransactionApi(key, new DapperTransactionApi(transaction, cancellationTokenProvider));
|
|
||||||
transactions.Add(key, transaction);
|
|
||||||
unitOfWorkManager.Current.OnCompleted(() =>
|
|
||||||
{
|
|
||||||
transaction = null;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return transaction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<NpgsqlConnection> GetOrCreateConnectionAsync(string cs)
|
private async Task<NpgsqlConnection> GetOrCreateConnectionAsync(string cs)
|
||||||
{
|
{
|
||||||
var key = $"Dapper_{cs}";
|
var key = BuildKey(cs);
|
||||||
var connection = connections.GetOrDefault(key);
|
if (!_connections.TryGetValue(key, out var connection))
|
||||||
if (connection == null)
|
|
||||||
{
|
{
|
||||||
connection = new NpgsqlConnection(cs);
|
connection = new NpgsqlConnection(cs);
|
||||||
connections.Add(key, connection);
|
_connections[key] = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connection.State == ConnectionState.Broken)
|
||||||
|
{
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
|
||||||
if (connection.State != ConnectionState.Open)
|
if (connection.State != ConnectionState.Open)
|
||||||
{
|
{
|
||||||
await connection.OpenAsync();
|
await connection.OpenAsync(_cancellationTokenProvider.FallbackToProvider(default));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_unitOfWorkManager.Current != null)
|
||||||
|
{
|
||||||
|
_unitOfWorkManager.Current.OnCompleted(async () =>
|
||||||
|
{
|
||||||
|
if (_connections.TryGetValue(key, out var conn))
|
||||||
|
{
|
||||||
|
_connections.Remove(key);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (conn.State != ConnectionState.Closed)
|
||||||
|
{
|
||||||
|
await conn.CloseAsync();
|
||||||
|
}
|
||||||
|
conn.Dispose();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<DbTransaction> GetOrCreateTransactionAsync(NpgsqlConnection con, string cs)
|
||||||
|
{
|
||||||
|
var key = BuildKey(cs);
|
||||||
|
|
||||||
|
if (_transactions.TryGetValue(key, out var tx))
|
||||||
|
{
|
||||||
|
if (tx?.Connection != null &&
|
||||||
|
tx.Connection == con &&
|
||||||
|
tx.Connection.State == ConnectionState.Open)
|
||||||
|
{
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { tx?.Dispose(); } catch { }
|
||||||
|
_transactions.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
var newTx = await con.BeginTransactionAsync(_cancellationTokenProvider.FallbackToProvider(default));
|
||||||
|
_transactions[key] = newTx;
|
||||||
|
|
||||||
|
if (_unitOfWorkManager.Current != null)
|
||||||
|
{
|
||||||
|
_unitOfWorkManager.Current.AddTransactionApi(
|
||||||
|
key,
|
||||||
|
new DapperTransactionApi(newTx, _cancellationTokenProvider)
|
||||||
|
);
|
||||||
|
|
||||||
|
_unitOfWorkManager.Current.OnCompleted(() =>
|
||||||
|
{
|
||||||
|
_transactions.Remove(key);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Dapper metotları ------------------
|
||||||
|
|
||||||
public virtual async Task<List<T>> QueryAsync<T>(string sql, string cs, Dictionary<string, object> parameters = null)
|
public virtual async Task<List<T>> QueryAsync<T>(string sql, string cs, Dictionary<string, object> parameters = null)
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
return (await dbConnection.QueryAsync<T>(sql, param, transaction)).AsList();
|
|
||||||
|
var result = await dbConnection.QueryAsync<T>(sql, param, transaction);
|
||||||
|
return result.AsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<IEnumerable<dynamic>> QueryAsync(string sql, string cs, Dictionary<string, object> parameters = null)
|
public virtual async Task<IEnumerable<dynamic>> QueryAsync(string sql, string cs, Dictionary<string, object> parameters = null)
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.QueryAsync(sql, param, transaction);
|
return await dbConnection.QueryAsync(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,7 +146,8 @@ public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.QuerySingleAsync<T>(sql, param, transaction);
|
return await dbConnection.QuerySingleAsync<T>(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,25 +155,30 @@ public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.ExecuteScalarAsync<T>(sql, param, transaction);
|
return await dbConnection.ExecuteScalarAsync<T>(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<T> GetSingleField<T>(string cs, string tableName, string id, string selectFieldName, string idFieldName = "Id")
|
public virtual async Task<T> GetSingleField<T>(string cs, string tableName, string id, string selectFieldName, string idFieldName = "Id")
|
||||||
{
|
{
|
||||||
var param = new { ID = id };
|
var param = new { ID = id };
|
||||||
string sql = $"select {selectFieldName} from {tableName} where {idFieldName} = @ID ";
|
var sql = $"select {selectFieldName} from {tableName} where {idFieldName} = @ID ";
|
||||||
|
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.QueryFirstAsync<T>(sql, param, transaction);
|
return await dbConnection.QueryFirstAsync<T>(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> UpdateField(string cs, string tableName, string id, string updateFieldName, string value, string idFieldName = "Id")
|
public virtual async Task<int> UpdateField(string cs, string tableName, string id, string updateFieldName, string value, string idFieldName = "Id")
|
||||||
{
|
{
|
||||||
var param = new { ID = id };
|
var param = new { ID = id };
|
||||||
string sql = $"update {tableName} set {updateFieldName} = '{value}' where Id = @ID ";
|
var sql = $"update {tableName} set {updateFieldName} = '{value}' where {idFieldName} = @ID ";
|
||||||
|
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,10 +186,13 @@ public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
{
|
{
|
||||||
var param = new DynamicParameters(parameters);
|
var param = new DynamicParameters(parameters);
|
||||||
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
var dbConnection = await GetOrCreateConnectionAsync(cs);
|
||||||
var transaction = await GetOrCreateTransactionAsync(dbConnection);
|
var transaction = await GetOrCreateTransactionAsync(dbConnection, cs);
|
||||||
|
|
||||||
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
return await dbConnection.ExecuteAsync(sql, param, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------ Dispose ------------------
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
|
|
@ -131,23 +201,40 @@ public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
private void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (IsDisposed)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
foreach (var connection in connections.Values)
|
foreach (var tx in _transactions.Values)
|
||||||
|
{
|
||||||
|
try { tx?.Dispose(); } catch { }
|
||||||
|
}
|
||||||
|
_transactions.Clear();
|
||||||
|
|
||||||
|
foreach (var connection in _connections.Values)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
if (connection.State == ConnectionState.Open)
|
if (connection.State != ConnectionState.Closed)
|
||||||
{
|
{
|
||||||
connection.Close();
|
connection.Close();
|
||||||
}
|
}
|
||||||
connection.Dispose();
|
connection.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
_connections.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,9 @@
|
||||||
"props": null,
|
"props": null,
|
||||||
"description": null,
|
"description": null,
|
||||||
"isActive": true,
|
"isActive": true,
|
||||||
"dependencies": ["DynamicEntityComponent"]
|
"dependencies": [
|
||||||
|
"DynamicEntityComponent"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ReportCategories": [
|
"ReportCategories": [
|
||||||
|
|
@ -2406,7 +2408,12 @@
|
||||||
"minSalary": 80000,
|
"minSalary": 80000,
|
||||||
"maxSalary": 120000,
|
"maxSalary": 120000,
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"requiredSkills": ["JavaScript", "TypeScript", "React", "Node.js"],
|
"requiredSkills": [
|
||||||
|
"JavaScript",
|
||||||
|
"TypeScript",
|
||||||
|
"React",
|
||||||
|
"Node.js"
|
||||||
|
],
|
||||||
"responsibilities": [
|
"responsibilities": [
|
||||||
"Develop frontend and backend applications",
|
"Develop frontend and backend applications",
|
||||||
"Write clean and maintainable code",
|
"Write clean and maintainable code",
|
||||||
|
|
@ -4101,7 +4108,9 @@
|
||||||
{
|
{
|
||||||
"postContent": "CI/CD pipeline güncellememiz tamamlandı! Deployment süremiz %40 azaldı. Otomasyonun gücü 💪",
|
"postContent": "CI/CD pipeline güncellememiz tamamlandı! Deployment süremiz %40 azaldı. Otomasyonun gücü 💪",
|
||||||
"type": "video",
|
"type": "video",
|
||||||
"urls": ["https://www.w3schools.com/html/mov_bbb.mp4"]
|
"urls": [
|
||||||
|
"https://www.w3schools.com/html/mov_bbb.mp4"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"SocialPollOptions": [
|
"SocialPollOptions": [
|
||||||
|
|
@ -4256,5 +4265,82 @@
|
||||||
"parentGroupCode": "MAMUL",
|
"parentGroupCode": "MAMUL",
|
||||||
"isActive": true
|
"isActive": true
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"Materials": [
|
||||||
|
{
|
||||||
|
"code": "MT001",
|
||||||
|
"name": "Yüksek Kaliteli Çelik Levha 10mm",
|
||||||
|
"barcode": "1234567890123",
|
||||||
|
"description": "Çelik Levha 2mm",
|
||||||
|
"materialTypeCode": "RAW",
|
||||||
|
"materialGroupCode": "METAL",
|
||||||
|
"uomName": "kg",
|
||||||
|
"costPrice": 15.5,
|
||||||
|
"salesPrice": 18.75,
|
||||||
|
"currencyCode": "TRY",
|
||||||
|
"isActive": true,
|
||||||
|
"totalStock": 2500.0,
|
||||||
|
"trackingType": "Quantity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MT002",
|
||||||
|
"name": "Alüminyum Profil 40x40",
|
||||||
|
"barcode": "1234567890124",
|
||||||
|
"description": "Alüminyum Profil 40x40",
|
||||||
|
"materialTypeCode": "SEMI",
|
||||||
|
"materialGroupCode": "METAL",
|
||||||
|
"uomName": "Adet",
|
||||||
|
"costPrice": 45.0,
|
||||||
|
"salesPrice": 55.0,
|
||||||
|
"currencyCode": "TRY",
|
||||||
|
"isActive": true,
|
||||||
|
"totalStock": 1200.0,
|
||||||
|
"trackingType": "Lot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PR001",
|
||||||
|
"name": "Montajlı Motor Grubu A-Type",
|
||||||
|
"barcode": "1234567890125",
|
||||||
|
"description": "Motor Grubu A-Type",
|
||||||
|
"materialTypeCode": "FINISHED",
|
||||||
|
"materialGroupCode": "MOTOR",
|
||||||
|
"uomName": "Adet",
|
||||||
|
"costPrice": 850.0,
|
||||||
|
"salesPrice": 1200.0,
|
||||||
|
"currencyCode": "TRY",
|
||||||
|
"isActive": true,
|
||||||
|
"totalStock": 45.0,
|
||||||
|
"trackingType": "Lot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SF001",
|
||||||
|
"name": "Kesme Yağı Premium",
|
||||||
|
"barcode": "1234567890126",
|
||||||
|
"description": "Kesme Yağı Premium",
|
||||||
|
"materialTypeCode": "FINISHED",
|
||||||
|
"materialGroupCode": "PLASTIK",
|
||||||
|
"uomName": "Adet",
|
||||||
|
"costPrice": 25.0,
|
||||||
|
"salesPrice": 35.0,
|
||||||
|
"currencyCode": "TRY",
|
||||||
|
"isActive": true,
|
||||||
|
"totalStock": 150.0,
|
||||||
|
"trackingType": "Quantity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PK001",
|
||||||
|
"name": "Plastik Kapak Komponenti",
|
||||||
|
"barcode": "1234567890127",
|
||||||
|
"description": "Plastik Kapak",
|
||||||
|
"materialTypeCode": "SEMI",
|
||||||
|
"materialGroupCode": "KIMYA",
|
||||||
|
"uomName": "Adet",
|
||||||
|
"costPrice": 8.5,
|
||||||
|
"salesPrice": 15.0,
|
||||||
|
"currencyCode": "TRY",
|
||||||
|
"isActive": true,
|
||||||
|
"totalStock": 850.0,
|
||||||
|
"trackingType": "Serial"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +94,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
private readonly IRepository<SocialLike, Guid> _socialLikeRepository;
|
private readonly IRepository<SocialLike, Guid> _socialLikeRepository;
|
||||||
private readonly IRepository<MaterialType, Guid> _materialTypeRepository;
|
private readonly IRepository<MaterialType, Guid> _materialTypeRepository;
|
||||||
private readonly IRepository<MaterialGroup, Guid> _materialGroupRepository;
|
private readonly IRepository<MaterialGroup, Guid> _materialGroupRepository;
|
||||||
|
private readonly IRepository<Material, Guid> _materialRepository;
|
||||||
|
|
||||||
public TenantDataSeeder(
|
public TenantDataSeeder(
|
||||||
IClock clock,
|
IClock clock,
|
||||||
|
|
@ -170,7 +171,8 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
IRepository<SocialComment, Guid> socialCommentRepository,
|
IRepository<SocialComment, Guid> socialCommentRepository,
|
||||||
IRepository<SocialLike, Guid> socialLikeRepository,
|
IRepository<SocialLike, Guid> socialLikeRepository,
|
||||||
IRepository<MaterialType, Guid> materialTypeRepository,
|
IRepository<MaterialType, Guid> materialTypeRepository,
|
||||||
IRepository<MaterialGroup, Guid> materialGroupRepository
|
IRepository<MaterialGroup, Guid> materialGroupRepository,
|
||||||
|
IRepository<Material, Guid> materialRepository
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_clock = clock;
|
_clock = clock;
|
||||||
|
|
@ -249,6 +251,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
_socialLikeRepository = socialLikeRepository;
|
_socialLikeRepository = socialLikeRepository;
|
||||||
_materialTypeRepository = materialTypeRepository;
|
_materialTypeRepository = materialTypeRepository;
|
||||||
_materialGroupRepository = materialGroupRepository;
|
_materialGroupRepository = materialGroupRepository;
|
||||||
|
_materialRepository = materialRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IConfigurationRoot BuildConfiguration()
|
private static IConfigurationRoot BuildConfiguration()
|
||||||
|
|
@ -1641,5 +1644,37 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
}, autoSave: true);
|
}, autoSave: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var item in items.Materials)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(item.Code))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var exists = await _materialRepository.AnyAsync(x => x.Code == item.Code);
|
||||||
|
if (exists)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var type = await _materialTypeRepository.FirstOrDefaultAsync(x => x.Code == item.MaterialTypeCode);
|
||||||
|
var group = await _materialGroupRepository.FirstOrDefaultAsync(x => x.Code == item.MaterialGroupCode);
|
||||||
|
var currency = await _currencyRepository.FirstOrDefaultAsync(x => x.Code == item.CurrencyCode);
|
||||||
|
var uom = await _uomRepository.FirstOrDefaultAsync(x => x.Name == item.UomName);
|
||||||
|
|
||||||
|
await _materialRepository.InsertAsync(new Material
|
||||||
|
{
|
||||||
|
Code = item.Code,
|
||||||
|
Name = item.Name,
|
||||||
|
Description = item.Description,
|
||||||
|
UomId = uom?.Id,
|
||||||
|
CostPrice = item.CostPrice,
|
||||||
|
SalesPrice = item.SalesPrice,
|
||||||
|
CurrencyId = currency?.Id,
|
||||||
|
IsActive = item.IsActive,
|
||||||
|
TotalStock = item.TotalStock,
|
||||||
|
MaterialTypeId = type?.Id,
|
||||||
|
MaterialGroupId = group?.Id,
|
||||||
|
Barcode = item.Barcode,
|
||||||
|
TrackingType = item.TrackingType
|
||||||
|
}, autoSave: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,6 @@ public class TenantSeederDto
|
||||||
public List<InterestingSeedDto> Interesting { get; set; }
|
public List<InterestingSeedDto> Interesting { get; set; }
|
||||||
public List<ProgramSeedDto> Programs { get; set; }
|
public List<ProgramSeedDto> Programs { get; set; }
|
||||||
|
|
||||||
//Supply Chain
|
|
||||||
public List<MaterialTypeSeedDto> MaterialTypes { get; set; }
|
|
||||||
public List<MaterialGroupSeedDto> MaterialGroups { get; set; }
|
|
||||||
|
|
||||||
//Hr
|
//Hr
|
||||||
public List<EmployeeTypeSeedDto> EmployeeTypes { get; set; }
|
public List<EmployeeTypeSeedDto> EmployeeTypes { get; set; }
|
||||||
public List<JobPositionSeedDto> JobPositions { get; set; }
|
public List<JobPositionSeedDto> JobPositions { get; set; }
|
||||||
|
|
@ -83,6 +79,28 @@ public class TenantSeederDto
|
||||||
public List<SocialPollOptionSeedDto> SocialPollOptions { get; set; }
|
public List<SocialPollOptionSeedDto> SocialPollOptions { get; set; }
|
||||||
public List<SocialCommentSeedDto> SocialComments { get; set; }
|
public List<SocialCommentSeedDto> SocialComments { get; set; }
|
||||||
public List<SocialLikeSeedDto> SocialLikes { get; set; }
|
public List<SocialLikeSeedDto> SocialLikes { get; set; }
|
||||||
|
|
||||||
|
//Supply Chain
|
||||||
|
public List<MaterialTypeSeedDto> MaterialTypes { get; set; }
|
||||||
|
public List<MaterialGroupSeedDto> MaterialGroups { get; set; }
|
||||||
|
public List<MaterialSeedDto> Materials { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MaterialSeedDto
|
||||||
|
{
|
||||||
|
public string Code { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Barcode { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string MaterialTypeCode { get; set; }
|
||||||
|
public string MaterialGroupCode { get; set; }
|
||||||
|
public string UomName { get; set; }
|
||||||
|
public decimal CostPrice { get; set; }
|
||||||
|
public decimal SalesPrice { get; set; }
|
||||||
|
public string CurrencyCode { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public decimal TotalStock { get; set; }
|
||||||
|
public string TrackingType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MaterialTypeSeedDto
|
public class MaterialTypeSeedDto
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"BaseDomain": "sozsoft.com"
|
"BaseDomain": "sozsoft.com"
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;",
|
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;",
|
||||||
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"BaseDomain": "sozsoft.com"
|
"BaseDomain": "sozsoft.com"
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;",
|
"SqlServer": "Server=sql;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;",
|
||||||
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=postgres;Port=5432;Database=Erp;"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"Version": "1.0.1"
|
"Version": "1.0.1"
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"SqlServer": "Server=localhost;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;",
|
"SqlServer": "Server=localhost;Database=Erp;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;Encrypt=False;TrustServerCertificate=True;Connection Timeout=60;",
|
||||||
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=localhost;Port=5432;Database=Erp;"
|
"PostgreSql": "User ID=sa;Password=NvQp8s@l;Host=localhost;Port=5432;Database=Erp;"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ function TenantConnectionString({
|
||||||
'value',
|
'value',
|
||||||
'Server=sql;Database=' +
|
'Server=sql;Database=' +
|
||||||
name +
|
name +
|
||||||
';User Id=sa;password=@Password;Trusted_Connection=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;',
|
';User Id=sa;password=@Password;Trusted_Connection=False;TrustServerCertificate=True;Connection Timeout=60;',
|
||||||
)
|
)
|
||||||
else if (option?.value == 2)
|
else if (option?.value == 2)
|
||||||
//MsSql
|
//MsSql
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue