ASP.net Core Rules Engine: Если первое правило не удается, другие правила не выполняютсяC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 ASP.net Core Rules Engine: Если первое правило не удается, другие правила не выполняются

Сообщение Anonymous »

Я работаю над системой продвижения в ядре ASP.NET, используя библиотеку правил (правила engine.models). Моя цель - применять несколько правил продвижения по службе, но у меня есть проблема, когда, если первое правило не удается, остальные правила не оцениваются. Активные правила продвижения из базы данных.
Оцените каждое правило независимо (так что даже если кто -то не удается, другие все еще работают).
Если условие правила не выполнено, пропустите его, но продолжайте оценивать следующие правила. Br /> Убедитесь, что скидки применяются только один раз на элемент (избегайте дублирующих расчетов). < /p>
Описание задачи: < /p>
В настоящее время я получаю правила из базы данных и Выполните их один за другим.
Однако, если условие первого правила неверно, следующие правила не выполняются.
Пример правил: < /p>
"Receipt.Rows.Sum(r => r.Qta) > 10"
"Receipt.Rows.Any(r => r.Cd_AR == \"1\")"
< /code>
Если первое условие (receipt.rows.sum (r => r.qta)> 10) является false,
→ второе условие (chestipt.rows.any ( r => r.cd_ar == "1")) никогда не проверяется.
Мне нужны все правила, которые должны быть оценены, даже если некоторые сбой. < /p>
Мой текущий код: < Br /> ApplyProMozioni (Controller) < /p>
`[HttpPost("apply")]
public async Task ApplyPromozioni(Receipt receipt)
{
RuleEvaluator.SetReceipt(receipt, clusterARRepository);

var regole = await GetRegoleAttive();
if (!regole.Any()) return Ok(receipt);

var orderedRules = regole.OrderBy(r => r.Priorita).ToList();
Console.WriteLine($"[DEBUG] Total Rules to Evaluate: {orderedRules.Count}");

var reSettings = new ReSettings
{
CustomActions = new Dictionary(),
IgnoreException = true,
};

foreach (var rule in orderedRules)
{
if (!reSettings.CustomActions.ContainsKey(rule.Azione))
{
reSettings.CustomActions[rule.Azione] = () => CreateActionInstance(rule.Azione, receipt);
}
}

var engine = new RulesEngine.RulesEngine(reSettings);

foreach (var rule in orderedRules)
{
try
{
Console.WriteLine($"[DEBUG] Evaluating Rule: {rule.Condizione}");

bool conditionMet = RuleEvaluator.EvaluateGeneralCondition(rule.Condizione);
Console.WriteLine($"[DEBUG] Rule Result: {rule.Condizione} => {conditionMet}");

if (!conditionMet)
{
Console.WriteLine($"⚠️ [DEBUG] Rule {rule.Condizione} FAILED, skipping...");
continue;
}

var workflow = new Workflow
{
WorkflowName = $"Workflow_{rule.Nome}",
Rules = new List
{
new Rule
{
RuleName = rule.Nome,
Expression = "true", // 🔥 **Forces the action to always run**
Actions = new RuleActions
{
OnSuccess = new ActionInfo
{
Name = rule.Azione,
Context = new Dictionary { { "Receipt", receipt } }
}
}
}
}
};

engine.AddOrUpdateWorkflow(new[] { workflow });

var result = await engine.ExecuteAllRulesAsync(workflow.WorkflowName, new { Receipt = receipt });

foreach (var res in result)
{
Console.WriteLine($"✅ {res.Rule.RuleName} - Success: {res.IsSuccess}");

if (res.IsSuccess)
{
receipt = res.ActionResult.Output as Receipt;
Console.WriteLine($"✅ Applied Rule: {res.Rule.RuleName}");
}
else
{
Console.WriteLine($"⚠️ Rule '{res.Rule.RuleName}' did not apply. Continuing to next rule...");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"❌ [ERROR] Rule {rule.Nome} failed: {ex.Message}. Skipping this rule and continuing...");
}
}

Console.WriteLine($"{JsonConvert.SerializeObject(receipt, Formatting.Indented)}");

return Ok(receipt);
}
`
< /code>
Applydiscountrule < /p>
public class ApplyDiscountRule : ActionBase
{
private readonly Receipt _receipt;
private readonly IPromozioneRuleRepository _promozioneRuleRepository;
private readonly IClusterARRepository _clusterARRepository;

public ApplyDiscountRule(Receipt receipt, IPromozioneRuleRepository promozioneRuleRepository, IClusterARRepository clusterARRepository)
{
_receipt = receipt;
_promozioneRuleRepository = promozioneRuleRepository;
_clusterARRepository = clusterARRepository;
}

public override async ValueTask Run(ActionContext context, RuleParameter[] ruleParameters)
{
// **Kuralları DB'den çek**
var rulesFromDb = (await _promozioneRuleRepository.GetActivePromotionRulesAsync())
.OrderBy(r => r.Priorita) // Önceliğe göre sırala
.ToList();

if (!rulesFromDb.Any())
{
Console.WriteLine($"⚠️ [WARNING] No active promotion rules found in DB.");
return _receipt;
}

RuleEvaluator.SetReceipt(_receipt, _clusterARRepository);

var generalRules = rulesFromDb
.Where(rule => !rule.Condizione.Contains("Receipt.Rows.Any(r => r.Cd_AR ==")) // Cluster ID içermeyen kurallar
.ToList();

foreach (var rule in generalRules)
{
if (RuleEvaluator.EvaluateGeneralCondition(rule.Condizione)) // Sadece genel koşulları değerlendir
{
Console.WriteLine($"✅ [DEBUG] General Rule Applied: {rule.Condizione}");

foreach (var row in _receipt.Rows)
{
string discountValue = DiscountHelper.ExtractDiscountValue(rule.Azione);
row.ScontoP = DiscountHelper.ApplySequentialDiscount(row.ScontoP ?? "0", discountValue);
Console.WriteLine($"✅ [DEBUG] Applied General Discount {discountValue}% to {row.Cd_AR}");
}
}
}

foreach (var row in _receipt.Rows)
{
Console.WriteLine($"🔍 [DEBUG] Checking row: {row.Cd_AR}, Qta: {row.Qta}");

var matchingRules = rulesFromDb
.Where(r => r.Condizione.Contains("Receipt.Rows.Any(r => r.Cd_AR =="))
.ToList();

foreach (var rule in matchingRules)
{
var match = Regex.Match(rule.Condizione, @"Receipt\.Rows\.Any\(r => r\.Cd_AR == \""(\d+)\""\)");
if (!match.Success)
{
Console.WriteLine($"[DEBUG] Skipping rule, no Cluster ID found: {rule.Condizione}");
continue;
}

int clusterId = int.Parse(match.Groups[1].Value);
Console.WriteLine($"[DEBUG] Found Cluster ID: {clusterId} in PromozioneRule");

var clusterData = await _clusterARRepository.GetByIdAsync(clusterId);
if (clusterData == null)
{
Console.WriteLine($"[ERROR] No ClusterAR found for Cluster ID: {clusterId}");
continue;
}

string clusterCdAR = clusterData.Cd_AR;
Console.WriteLine($"[DEBUG] Found Cd_AR for Cluster {clusterId}: {clusterCdAR}");

if (row.Cd_AR != clusterCdAR)
{
Console.WriteLine($"[DEBUG] Skipping row {row.Cd_AR}, not matching ClusterAR Cd_AR.");
continue;
}

if (row.Qta >= clusterData.Quantity)
{
string discountValue = DiscountHelper.ExtractDiscountValue(rule.Azione);
row.ScontoP = DiscountHelper.ApplySequentialDiscount(row.ScontoP ?? "0", discountValue);
Console.WriteLine($"✅ [DEBUG] Applied Discount {discountValue}% to {row.Cd_AR}");
}
else
{
Console.WriteLine($"❌ [DEBUG] {row.Cd_AR} does not meet quantity requirement for Cluster {clusterId}. Skipping.");
}
}
}

return _receipt;
}
}
< /code>
То, что я попробовал и не работал:
принуждение всех правил запустить
i set Expression = "true" в правилах Engine для заставления правил выполнять,
Но все же, когда первое правило не удалось, другие не выполняются правильно. .
вручную зацикливание по правилам
Даже если я прохожу через каждое правило один за другим,
Если первое не удалось, Applydiscountrule не выполняется для остальных. < /p>
Мой вопрос:
Как я могу убедиться, что все правила работают независимо, даже если некоторые терпят неудачу?
Я хочу, чтобы каждое правило было оценено одно за другим. Следует просто пропустить, но другие все еще должны работать.
Как я могу изменить свою реализацию для достижения этой < /p>

Подробнее здесь: https://stackoverflow.com/questions/794 ... t-executed
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»