seed/data Seeder GlobalSearch

This commit is contained in:
Sedat ÖZTÜRK 2026-09-04 14:25:35 +03:00
parent 3db82df964
commit a1a76b1a95
6 changed files with 74 additions and 64 deletions

View file

@ -3434,6 +3434,9 @@ Kurallar:
- **Anahtar dosyada durur.** Insert varsayılanları anahtarı `@NEWID` ile üretir; `ListFormSeedDataApplier` - **Anahtar dosyada durur.** Insert varsayılanları anahtarı `@NEWID` ile üretir; `ListFormSeedDataApplier`
dosyadaki anahtarı geri yazar, böylece aynı dosya birden çok kez uygulandığında kopya kayıt oluşmaz. dosyadaki anahtarı geri yazar, böylece aynı dosya birden çok kez uygulandığında kopya kayıt oluşmaz.
Elle dosya yazarken anahtarı deterministik üret (ör. koddan türeyen GUID). Elle dosya yazarken anahtarı deterministik üret (ör. koddan türeyen GUID).
- **Identity anahtarlı tablolarda satır anahtarsız yazılır.** `Id` alanı dosyada yoksa anahtar
veritabanına bırakılır; satırın var olup olmadığı dosyadaki **tüm alan değerlerinin**
(tenant kapsamı dahil) eşleşmesine bakılarak belirlenir.
- **Uygulama yalnızca ekler:** anahtarı veritabanında bulunmayan satırlar `INSERT` edilir; var olan - **Uygulama yalnızca ekler:** anahtarı veritabanında bulunmayan satırlar `INSERT` edilir; var olan
kayıt güncellenmez (her migrate'te ekrandaki güncel değerler dosyadaki eskisiyle ezilmesin diye) kayıt güncellenmez (her migrate'te ekrandaki güncel değerler dosyadaki eskisiyle ezilmesin diye)
ve dosyada olmayan satır silinmez. ve dosyada olmayan satır silinmez.

View file

@ -1145,6 +1145,10 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.GlobalSearch)), SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.GlobalSearch)),
KeyFieldName = "Id", KeyFieldName = "Id",
KeyFieldDbSourceType = DbType.Int32, KeyFieldDbSourceType = DbType.Int32,
SeedFilePath = SeedPathResolver.GetDataFilePath(listFormName),
SeedSyncInsert = false,
SeedSyncUpdate = false,
SeedSyncDelete = false,
SortMode = GridOptions.SortModeSingle, SortMode = GridOptions.SortModeSingle,
FilterRowJson = DefaultFilterRowJson(), FilterRowJson = DefaultFilterRowJson(),
HeaderFilterJson = DefaultHeaderFilterJson(), HeaderFilterJson = DefaultHeaderFilterJson(),

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -138,7 +138,11 @@ public class ListFormSeedDataApplier(
} }
} }
/// <summary>Satiri ekler; kayit eklendiyse <c>true</c>, ayni anahtarli kayit zaten varsa <c>false</c> doner.</summary> /// <summary>
/// Satiri ekler; kayit eklendiyse <c>true</c>, ayni kayit zaten varsa <c>false</c> doner.
/// Dosyada anahtar yoksa (identity kolonlu tablolar) satir diger alanlarinin tamami uzerinden
/// eslesir ve anahtar veritabanina biraktirilir.
/// </summary>
private async Task<bool> ApplyRowAsync( private async Task<bool> ApplyRowAsync(
ListForm listForm, ListForm listForm,
List<ListFormField> fields, List<ListFormField> fields,
@ -154,37 +158,59 @@ public class ListFormSeedDataApplier(
row.GetValueOrDefault(keyFieldName)); row.GetValueOrDefault(keyFieldName));
object[] keys = [keyValue]; object[] keys = [keyValue];
var hasKey = keyValue != null;
var insertParameters = BuildParameters(fields, row, keyFieldName, includeKey: hasKey);
// Var olan kayda dokunulmaz: veritabanindaki guncel deger, dosyadaki eski degerle ezilmemeli. // Var olan kayda dokunulmaz: veritabanindaki guncel deger, dosyadaki eski degerle ezilmemeli.
if (await ExistsAsync(listForm, keyFieldName, keyValue, repository, connectionString)) var match = hasKey
? new Dictionary<string, object> { [keyFieldName] = keyValue }
: new Dictionary<string, object>(insertParameters);
if (!hasKey && PlatformConsts.IsMultiTenant && listForm.IsTenant)
{
match["TenantId"] = currentTenant.Id;
}
if (await ExistsAsync(listForm, match, repository, connectionString))
{ {
return false; return false;
} }
var insertParameters = BuildParameters(fields, row, keyFieldName, includeKey: true);
await MergeDefaultsAsync(listForm, fields, OperationEnum.Insert, keys, insertParameters); await MergeDefaultsAsync(listForm, fields, OperationEnum.Insert, keys, insertParameters);
// Insert varsayilanlari anahtari @NEWID ile uretir; dosyadaki anahtar korunmazsa ayni if (hasKey)
// dosya her uygulandiginda yeni kayit olusurdu. {
insertParameters[keyFieldName] = keyValue; // Insert varsayilanlari anahtari @NEWID ile uretir; dosyadaki anahtar korunmazsa ayni
// dosya her uygulandiginda yeni kayit olusurdu.
insertParameters[keyFieldName] = keyValue;
}
else
{
// Anahtari veritabani uretir; parametre listesinde kalirsa identity kolonuna
// acik deger yazilmaya calisilir.
insertParameters.Remove(keyFieldName);
}
var insertSql = queryManager.GenerateQuery(listForm, fields, insertParameters, OperationEnum.Insert, dataSourceType, keys); var insertSql = queryManager.GenerateQuery(listForm, fields, insertParameters, OperationEnum.Insert, dataSourceType, keys);
await repository.ExecuteAsync(insertSql, connectionString, insertParameters); await repository.ExecuteAsync(insertSql, connectionString, insertParameters);
return true; return true;
} }
/// <summary>Ayni anahtara sahip bir kayit hedef tabloda var mi.</summary> /// <summary>Verilen alan degerleriyle eslesen bir kayit hedef tabloda var mi.</summary>
private static async Task<bool> ExistsAsync( private static async Task<bool> ExistsAsync(
ListForm listForm, ListForm listForm,
string keyFieldName, Dictionary<string, object> match,
object keyValue,
IDynamicDataRepository repository, IDynamicDataRepository repository,
string connectionString) string connectionString)
{ {
var sql = $"SELECT COUNT(1) FROM \"{listForm.SelectCommand}\" WHERE \"{keyFieldName}\" = @{keyFieldName}"; var where = string.Join(
var parameters = new Dictionary<string, object> { [keyFieldName] = keyValue }; " AND ",
match.Select(a => a.Value == null ? $"\"{a.Key}\" IS NULL" : $"\"{a.Key}\" = @{a.Key}"));
return await repository.ExecuteScalarAsync<int>(sql, connectionString, parameters) > 0; var sql = $"SELECT COUNT(1) FROM \"{listForm.SelectCommand}\" WHERE {where}";
return await repository.ExecuteScalarAsync<int>(sql, connectionString, match) > 0;
} }
/// <summary> /// <summary>

View file

@ -1,27 +1,4 @@
{ {
"GlobalSearch": [
{
"system": "Platform",
"group": "Setting Definitions",
"term": "Abp.Account.Captcha.EndPoint",
"weight": "0.2",
"url": "/admin/list/App.SettingDefinitions"
},
{
"system": "Platform",
"group": "Setting Definitions",
"term": "Abp.Account.IsSelfRegistrationEnabled",
"weight": "0.8",
"url": "/admin/list/App.SettingDefinitions"
},
{
"system": "Platform",
"group": "Setting Definitions",
"term": "Abp.Account.IsSelfRegistrationEnabled",
"weight": "0.7",
"url": "/admin/list/App.SettingDefinitions"
}
],
"ForumCategories": [ "ForumCategories": [
{ {
"Name": "Genel Tartışma", "Name": "Genel Tartışma",

View file

@ -21,7 +21,6 @@ namespace Sozsoft.Platform.Data.Seeds;
public class TenantSeederDto public class TenantSeederDto
{ {
//Saas //Saas
public List<GlobalSearchSeedDto> GlobalSearch { get; set; }
public List<CustomEndpointSeedDto> CustomEndpoints { get; set; } public List<CustomEndpointSeedDto> CustomEndpoints { get; set; }
public List<SequenceSeedDto> Sequences { get; set; } public List<SequenceSeedDto> Sequences { get; set; }
@ -224,15 +223,6 @@ public class DepartmentSeedDto
public string ParentName { get; set; } public string ParentName { get; set; }
} }
public class GlobalSearchSeedDto
{
public string System { get; set; }
public string Group { get; set; }
public string Term { get; set; }
public string Weight { get; set; }
public string Url { get; set; }
}
public class UomCategorySeedDto public class UomCategorySeedDto
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
@ -430,7 +420,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
{ {
private readonly ILookupNormalizer _lookupNormalizer; private readonly ILookupNormalizer _lookupNormalizer;
private readonly IRepository<Branch, Guid> _branchRepository; private readonly IRepository<Branch, Guid> _branchRepository;
private readonly IRepository<GlobalSearch, int> _globalSearch;
private readonly IRepository<CustomEndpoint, Guid> _customEndpointRepository; private readonly IRepository<CustomEndpoint, Guid> _customEndpointRepository;
private readonly IRepository<ReportCategory, Guid> _reportCategoriesRepository; private readonly IRepository<ReportCategory, Guid> _reportCategoriesRepository;
private readonly IRepository<ReportTemplate, Guid> _reportTemplatesRepository; private readonly IRepository<ReportTemplate, Guid> _reportTemplatesRepository;
@ -471,7 +460,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
ILookupNormalizer lookupNormalizer, ILookupNormalizer lookupNormalizer,
IIdentityUserRepository repositoryUser, IIdentityUserRepository repositoryUser,
IRepository<Branch, Guid> branchRepository, IRepository<Branch, Guid> branchRepository,
IRepository<GlobalSearch, int> globalSearch,
IRepository<UomCategory, string> uomCategoryRepository, IRepository<UomCategory, string> uomCategoryRepository,
IRepository<Uom, string> uomRepository, IRepository<Uom, string> uomRepository,
IRepository<SkillType, string> skillTypeRepository, IRepository<SkillType, string> skillTypeRepository,
@ -510,7 +498,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
_lookupNormalizer = lookupNormalizer; _lookupNormalizer = lookupNormalizer;
_repositoryUser = repositoryUser; _repositoryUser = repositoryUser;
_branchRepository = branchRepository; _branchRepository = branchRepository;
_globalSearch = globalSearch;
_uomCategoryRepository = uomCategoryRepository; _uomCategoryRepository = uomCategoryRepository;
_uomRepository = uomRepository; _uomRepository = uomRepository;
_skillTypeRepository = skillTypeRepository; _skillTypeRepository = skillTypeRepository;
@ -559,21 +546,6 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
foreach (var item in items.GlobalSearch)
{
if (!await _globalSearch.AnyAsync(x => x.System == item.System && x.Group == item.Group && x.Term == item.Term))
{
await _globalSearch.InsertAsync(new GlobalSearch
{
System = item.System,
Group = item.Group,
Term = item.Term,
Weight = item.Weight,
Url = item.Url
});
}
}
foreach (var item in items.UomCategories) foreach (var item in items.UomCategories)
{ {
var exists = await _uomCategoryRepository.AnyAsync(x => x.Name == item.Name); var exists = await _uomCategoryRepository.AnyAsync(x => x.Name == item.Name);

View file

@ -0,0 +1,28 @@
{
"ListFormCode": "App.Definitions.GlobalSearch",
"KeyFieldName": "Id",
"GeneratedAt": "2026-09-04T00:00:00Z",
"Rows": [
{
"System": "Platform",
"Group": "Setting Definitions",
"Term": "Abp.Account.Captcha.EndPoint",
"Url": "/admin/list/App.SettingDefinitions",
"Weight": "0.2"
},
{
"System": "Platform",
"Group": "Setting Definitions",
"Term": "Abp.Account.IsSelfRegistrationEnabled",
"Url": "/admin/list/App.SettingDefinitions",
"Weight": "0.8"
},
{
"System": "Platform",
"Group": "Setting Definitions",
"Term": "Abp.Account.IsSelfRegistrationEnabled",
"Url": "/admin/list/App.SettingDefinitions",
"Weight": "0.7"
}
]
}