A few days ago a developer at a customer asked me how he could simplify the following code as he identified a pattern: X tries and the error handling.


public PlanungsGruppenLesenA PlanungsGruppenLesen(
    PlanungsGruppenLesenF param)
{
    PlanungsGruppenLesenA ret = new PlanungsGruppenLesenA();
 
    if (ret.PlanungsGruppen == null)
    {
        throw new ArgumentNullException("param.PlanungsGruppen");
    }
    int nRetry = 0;
    while (nRetry < DBWerkzeug.MaxWiederholungen)
    {
        try
        {
            using (XXX_POC.POC db =
                new XXX_POC.POC(
                    DBWerkzeug.GetConnectionString()))
            {
                var q =
                    from p in db.Stammdaten_Planungsgruppe
                    orderby p.Name.ToLower()
                    select new PlanungsGruppeDM
                    {
                        ID = p.Rowid,
                        Name = p.Name
                    };
                ret.PlanungsGruppen = q.ToList<PlanungsGruppeDM>();
            }
        }
        catch (ChangeConflictException e)
        {
            nRetry++;
            if (nRetry >= DBWerkzeug.MaxWiederholungen)
            {
                ret.FehlerText = e.Message;
                ret.HatFehler = true;
                throw;
            }
        }
        catch (Exception e)
        {
            ret.FehlerText = e.Message;
            ret.HatFehler = true;
            throw;
        }
    }
    return ret;
}

I ended up with this:


public PlanungsGruppenLesenA PlanungsGruppenLesen(
    PlanungsGruppenLesenF param)
{
    PlanungsGruppenLesenA ret = new PlanungsGruppenLesenA();
 
    if (ret.PlanungsGruppen == null)
    {
        throw new ArgumentNullException("param.PlanungsGruppen");
    }
    ret.PlanungsGruppen = CatchExceptions<PlanungsGruppeDM>(
        delegate
        {
            using (XXX_POC.POC db =
                new XXX_POC.POC(
                    DBWerkzeug.GetConnectionString()))
            {
                var q =
                    from p in db.Stammdaten_Planungsgruppe
                    orderby p.Name.ToLower()
                    select new PlanungsGruppeDM
                    {
                        ID = p.Rowid,
                        Name = p.Name
                    };
                return q.ToList<PlanungsGruppeDM>();
            }
        },
        ret);           
    return ret;
}

What calls the encapsulated X tries and the error handling:


public delegate List<T> MachMal<T>();
 
public static List<T> CatchExceptions<T>(MachMal<T> machMichFertig, BasisA ret)
{
    int nRetry = 0;
    while (nRetry < DBWerkzeug.MaxWiederholungen)
    {
        try
        {
            return machMichFertig();
        }
        catch (ChangeConflictException e)
        {
            nRetry++;
            if (nRetry >= DBWerkzeug.MaxWiederholungen)
            {
                ret.FehlerText = e.Message;
                ret.HatFehler = true;
                throw;
            }
        }
        catch (Exception e)
        {
            ret.FehlerText = e.Message;
            ret.HatFehler = true;
            throw;
        }
    }
    return null;
}

But I’m not quite sure If this made stuff really easier ;-)