Übersetzungen
"ba98d63f-8b15-4b68-852f-102cbeb70d6e";"Service hinzufügen (Massenverarbeitung)";"Add service (Mass worker)";"";"";"";"False";"0"
"281e4152-6d03-40b4-9971-10728e673a00";"Services hinzufügen";"Add services";"";"";"";"False";"0"
"61bca157-96a6-436b-8719-0521b98462b9";"Starte Prozess";"Start process";"";"";"";"False";"0"
"227b79dd-31f2-4f6d-a255-94eb8aca0e89";"Neustart Prozess";"Restart process";"";"";"";"False";"0"
"03a9ae68-226f-4f19-91cd-47fa4370230b";"{0} zu verarbeiten";"{0} to process";"";"";"";"False";"0"
"e3d32867-83eb-4514-abec-c7e596ae192b";"{0} von {1} verarbeitet";"{0} of {1} processed";"";"";"";"False";"0"
"1cba5efa-7842-4764-abb8-05e2fab5bde3";"Maschine {0} wird verarbeitet.";"Engine {0} processing";"";"";"";"False";"0"
"0dd299df-c558-44fd-86ec-b3b2acd47530";"Keine Bearbeitungrechte für {0}";"No edit rights for {0}";"";"";"";"False";"0"
"cf6889ab-e880-42c9-8755-bfb15f9f01af";"Temporärer Datensatz wurde nicht gefunden: {0} / {1}";"Temporary record not found: {0} / {1}";"";"";"";"False";"0"
"160c2db4-e013-4569-8ab1-a37bdf776707";"Meine Ausnahme";"My exception";"";"";"";"False";"0"
Hintergrundprozess
Worker
public class AddServiceWorker : WorkItemBase
{
public Guid TaskExecutionId { get; set; }
public string Remark { get; set; }
public DateTime Date { get; set; }
public int MissingRights { get; set; }
public AddServiceWorker(): base()
{
ExpectedRunTime = EnumExpectedRunTime.Long;
}
protected override void Run()
{
IQueryable<OrmTempSelectedRecords> query = Api.ORM.GetQuery<OrmTempSelectedRecords>(UnitOfWork);
query = query.Where(ff => ff.TaskExecutionId == TaskExecutionId);
if (MaxProgress == 0)
MaxProgress = query.Count();
IQueryable<Guid> oids = query.Select(ff => ff.SelectedRecordOid);
IQueryable<OrmEngine> engines = Api.ORM.GetQuery<OrmEngine>(UnitOfWork).Where(ff => oids.Contains(ff.Oid));
foreach (OrmEngine engine in engines)
{
if (engine.IsAllowed(EnumTableOperations.Edit))
{
OrmSubEngineServices service = engine.Services.AddNewObject();
service.SortOrder = engine.Services.Count() - 1;
service.ServiceDate = Date;
service.Remark = Remark;
engine.Save();
}
else
MissingRights++;
query.Where(ff => ff.SelectedRecordOid == engine.Oid).FirstOrDefault()?.Delete();
if (CurrentProgress == 2 && NumberOfStarts == 1)
throw new Exception(Logger.Translate("160C2DB4-E013-4569-8AB1-A37BDF776707"));
CurrentProgress++;
Save();
}
}
protected override void WorkItemFinished()
{
if (State == EnumWorkItemState.Finished)
if (MissingRights == 0)
Api.ClientCommunication.CreateSuccess(Api.User.CurrentUserGuid(), "dd1ceadc-6808-4583-b6b7-dda73188b5a8".Translate(CurrentProgress));
else
Api.ClientCommunication.CreateSuccess(Api.User.CurrentUserGuid(), "e3f652e7-8019-4444-9e6c-f3c30528e862".Translate(CurrentProgress - MissingRights, MissingRights));
base.WorkItemFinished();
}
}
Igniter-Änderung
Die temporären Datensätze müssen angelegt werden.
CreateTemporaryRecordsIndicator = true;
Anstatt der Verarbeitung, wird nun der Hintergrundprozess erstellt.
public override ActionResult Ignite()
{
if (SomethingSelected)
{
if (IgnitionModel.Parameters.TryGetValue("RemarkMessage", out object remarkObj) && remarkObj is string remark && !string.IsNullOrWhiteSpace(remark))
{
DateTime date;
if (IgnitionModel.Parameters.TryGetValue("ServiceDate", out object dateObj) && dateObj is DateTime)
date = (DateTime)dateObj;
else
date = DateTime.Now;
Api.Worker.CreateOrUpdate(new AddServiceWorker
{
TaskExecutionId = TaskExecutionId,
Remark = remark,
Date = date
});
}
else
Api.ClientCommunication.CreateError(Api.User.CurrentUserGuid(), "d49ef787-3ad1-4f66-bb12-b2660fd71738".Translate());
}
return null;
}
Antworten
Warum wurde ein Anwendungsprotokoll geschrieben? Und wie kann man es verhindern?
Der Vorgabewert von LoggingMode
ist WorkerLoggingMode.Auto
, damit ist dem System gestattet im Zweifelsfall ein Protokoll zu erstellen.
LoggingMode = WorkerLoggingMode.Never
würde dies verhindern.
Wurden alle Datensätze korrekt verarbeitet?
Ja. Da der Arbeitsvorrat (die temporäre Tabelle) immer aktuell gehalten wurde. Beim Neustart wurde damit genau an dem Datensatz fortgesetzt bei dem der Fehler auftrat.
Massenverarbeitung
Aktion
[Serializable]
[Toolbox(EnumConfigurationType.NavigationConfigurationGuid, true)]
[ControlFilter("NavigationConfigurationType", ExpressionType.Equal, EnumNavigationConfigurationType.RibbonNavigationGuid, EnumControlFilterApplyState.IfPositive)]
public class ClientActionAddServiceMassWorker : ClientActionGridMassOperationBase, IOrmSecurityHandler, IIgnitableAction
{
[DisplayName("41ABA083-E37A-4709-98D4-1D685496459C")]
public string RemarkMessage { get; set; }
[TokenboxControl]
[CDPRolesProviderProperties(dataSources: new[] { EnumDataSource.RoleGuid })]
[DisplayName("BD0D11A9-9E71-4980-9265-C4A037432D48")]
public RoleSet DialogRoles { get; set; }
[Browsable(false)]
public string MessageOnSuccess { get; set; }
[Browsable(false)]
public string MessageOnError { get; set; }
[Browsable(false)]
public string MessageOnStart { get; set; }
[Browsable(false)]
public string ProgressBarProcessName { get; set; }
[Browsable(false)]
public string ProgressBarProcessDescription { get; set; }
public ClientActionAddServiceMassWorker() : base()
{
ToolboxName = "BA98D63F-8B15-4B68-852F-102CBEB70D6E";
Caption = "BA98D63F-8B15-4B68-852F-102CBEB70D6E";
ControlInitName = "TrainingActionAddServiceMassWorker";
ToolboxGroupName = "C007681C-8644-4BB0-A4A0-4A643265EABD";
Id = "D6F15F40-5A3F-4D02-AF5B-491C8705B7BC".ToGuid();
Icon = "wrench";
IconName = Icon;
VisibilityForParentTypes.Add(EnumActionVisibleForParentType.Grid);
MassOperationIgniter = typeof(OperationFromActionOverSelectedRecordsIgniter).AssemblyQualifiedName;
DynamicClientVisibility.Add(EnumActionVisibility.IfUserHasRole);
DynamicClientVisibility.Add(EnumActionVisibility.SomethingSelected);
SomethingMustBeSelected = true;
AdditionalClientData.AddOrUpdate("ActionMethodId", "BA.Training.ClientActionAddService");
}
public override void AdditionalRibbonButtonAssignment(DevExpress.Web.RibbonButtonItem ribbonItem, EnumActionVisibleForParentType parentType, DevExUIModelBase uiModel = null)
{
base.AdditionalRibbonButtonAssignment(ribbonItem, parentType, uiModel);
AdditionalClientData.AddOrUpdate("RemarkMessage", RemarkMessage);
AdditionalClientData.AddOrUpdate("DialogAuthorized", Api.User.CurrentUserIsInRole(DialogRoles, false));
}
public bool CanHandleOrm(object DataObject, OrmBABase orm)
{
bool canHandle;
if (orm != null)
canHandle = orm.IsAllowed(EnumTableOperations.Edit);
else
{
OrmEntityConfiguration entityConfig = Api.Config.OrmEntity(EnumDataSourceExtension.Engine.ValueGuid);
canHandle = entityConfig.IsAllowed(EnumTableOperations.Edit) != EnumTableOperations.Denied;
}
AdditionalClientData.AddOrUpdate("UserHasRole", canHandle);
return canHandle;
}
public Type GetWorkItemType()
{
return typeof(AddServiceMassWorker);
}
public void Ignite(IIgnitableWorkItem task, Guid tempKey, Guid? taskExecutionId, Dictionary<string, object> parameters, JsonFormResult result)
{
AddServiceMassWorker worker = (AddServiceMassWorker)task;
if (parameters.TryGetValue("RemarkMessage", out object remarkObj) && remarkObj is string remark && !string.IsNullOrWhiteSpace(remark))
{
DateTime date;
if (parameters.TryGetValue("ServiceDate", out object dateObj) && dateObj is DateTime)
date = (DateTime)dateObj;
else
date = DateTime.Now;
worker.Remark = remark;
worker.Date = date;
}
}
}
Erweiterung von EnumLogProcess
namespace BA.Training.Enums.Extensions
{
[EnumExtension(typeof(EnumLogProcesses))]
public static class EnumLogProcessesExtension
{
public const string AddServiceGuid = "FBF67FBA-9E64-4254-B168-A0C8DF806C63";
public static readonly EnumLogProcesses AddService = new EnumLogProcesses(AddServiceGuid, 1000, "281E4152-6D03-40B4-9971-10728E673A00");
}
}
Worker
public class AddServiceMassWorker : MassWorkItem, IIgnitableWorkItem
{
public Guid TemporaryGuid { get; set; }
public Guid TaskExecutionId { get; set; }
public string MessageOnSuccess { get; set; }
public string MessageOnError { get; set; }
public string ProgressBarProcessName { get; set; }
public string ProgressBarProcessDescription { get; set; }
public IIgnitableAction ClientAction { get; set; }
public string Remark { get; set; }
public DateTime Date { get; set; }
public int MissingRights { get; set; }
public AddServiceMassWorker() : base()
{
ScheduledStartTime = DateTime.UtcNow.AddMinutes(1);
IsCancellable = true;
LoggingProcess = EnumLogProcessesExtension.AddService;
Caption = "281e4152-6d03-40b4-9971-10728e673a00";
Title = "281e4152-6d03-40b4-9971-10728e673a00";
}
protected override IQueryable<OrmBABase> GetQueryable()
{
if (NumberOfStarts == 1)
Logger.AddInfo("61BCA157-96A6-436B-8719-0521B98462B9");
else
Logger.AddInfo("227B79DD-31F2-4F6D-A255-94EB8ACA0E89");
IQueryable<OrmTempSelectedRecords> query = Api.ORM.GetQuery<OrmTempSelectedRecords>(UnitOfWork);
query = query.Where(ff => ff.TaskExecutionId == TaskExecutionId);
if (MaxProgress == 0)
{
MaxProgress = query.Count();
Logger.AddInfo("03A9AE68-226F-4F19-91CD-47FA4370230B", MaxProgress);
throw new Exception(Logger.Translate("160C2DB4-E013-4569-8AB1-A37BDF776707"));
}
else
Logger.AddInfo("E3D32867-83EB-4514-ABEC-C7E596AE192B", CurrentProgress, MaxProgress);
IQueryable<Guid> oids = query.Select(ff => ff.SelectedRecordOid);
return Api.ORM.GetQuery<OrmEngine>(UnitOfWork).Where(ff => oids.Contains(ff.Oid));
}
protected override void ProcessSingleOrm(OrmBABase ormBABase)
{
OrmEngine engine = (OrmEngine)ormBABase;
Logger.AddInfo("1CBA5EFA-7842-4764-ABB8-05E2FAB5BDE3", engine.Name);
if (CurrentProgress == 2)
throw new Exception(Logger.Translate("160C2DB4-E013-4569-8AB1-A37BDF776707"));
if (engine.IsAllowed(EnumTableOperations.Edit))
{
OrmSubEngineServices service = engine.Services.AddNewObject();
service.SortOrder = engine.Services.Count() - 1;
service.ServiceDate = Date;
service.Remark = Remark;
engine.Save();
}
else
{
Logger.AddWarning("0DD299DF-C558-44FD-86EC-B3B2ACD47530", engine.Name);
MissingRights++;
}
IQueryable<OrmTempSelectedRecords> query = Api.ORM.GetQuery<OrmTempSelectedRecords>(UnitOfWork);
query = query.Where(ff => ff.TaskExecutionId == TaskExecutionId && ff.SelectedRecordOid == engine.Oid);
OrmTempSelectedRecords tempRecord = query.FirstOrDefault();
if (tempRecord != null)
tempRecord.Delete();
else
Logger.AddWarning("CF6889AB-E880-42C9-8755-BFB15F9F01AF", TaskExecutionId, engine.Oid);
CurrentProgress++;
}
protected override void WorkItemFinished()
{
if (State == EnumWorkItemState.Finished)
if (MissingRights == 0)
{
Api.ClientCommunication.CreateSuccess(Api.User.CurrentUserGuid(), "dd1ceadc-6808-4583-b6b7-dda73188b5a8".Translate(CurrentProgress));
Logger.AddInfo("dd1ceadc-6808-4583-b6b7-dda73188b5a8", CurrentProgress);
}
else
{
Api.ClientCommunication.CreateError(Api.User.CurrentUserGuid(), "e3f652e7-8019-4444-9e6c-f3c30528e862".Translate(CurrentProgress - MissingRights, MissingRights));
Logger.AddInfo("e3f652e7-8019-4444-9e6c-f3c30528e862", CurrentProgress - MissingRights, MissingRights);
}
base.WorkItemFinished();
}
}
Antworten
Was steht im Anwendungsprotokoll?
Wurden alle Datensätze verarbeitet?
Nein, der Datensatz mit der Exception wurde übersprungen.
Warum gibt es einen Unterschied zum vorherigen Hintergrundprozess, und was müsste man tun, um Fehlerhafte Datensätze nochmal zu vearbeiten?
Das MassWorkItem
überpringt Datensätze bei denen Ausnahmen auftreten.
Man muss in WorkItemFinished
den Worker in dem Fall mit AddSuccessor
nochmal starten. Dies macht aber nur Sinn, wenn der Fehler nicht dauerhaft ist.