EurekaFach .Net

EurekaFach .Net is a Windows desktop application that is used at specialised courts in Germany (mostly Arbeitsgerichte, Finanzgerichte, Sozialgerichte und Verwaltungsgerichte) to assist judges and judicial specialist who are responsible for the procedural management of lawsuits and other court procedures.

One of the many features of EurekaFach are keeping track of the current status of law suits, manage dates, appointments and addresses, manage all the documents involved in a law suit, calculate costs for procedural aids and compensations for honorary judges and providing the huge "Schreibwerk" to generate decrees, summons and other kind of court letters with the help of parameterized text building blocks, Microsoft Word templates, macros and XLST.

What EurekaFach is not doing is to replace a judge by rendering a judgement😉.

In April 2022 EurekaFach .Net is used by 250 courts in 14 of the 16 federal states in Germany by approximately 12.000 users.

EurekaFach .Net is the .Net version of EurekaFach. The development of EurekaFach started in 1998 and was completed in 1999 with the release of the first official version.

First a short summary of the application and its history:

  • The original EurekaFach started with VO, bBrowser, VO2Ado and ReportPro in 1998 and was completed in 1999
  • Over years the user bases growed rapidly
  • The development team consists of 6 developers
  • The migration to .Net started in 2018 and was completed in 2020
  • EurekaFach .Net ist based on .NET Framework 4.62 and uses X# 2.11
  • 3rd party components in use are DevExpress WinFormsUI Components and Office File API, Tx TextControl,Codejock, OracleManagedDataAccess and Devart PostgreSQL
  • Supported Databases: MS-SQL Server, Oracle, PostGreSQL
  • All the development is done with Visual Studio

A short time travel back to the year 1998. There were several reasons why a Windows Application for specialised courts in Germany was needed at that time:

  • It was already decided that the Unix system that was in use had to be replaced by Windows PCs
  • A general demand to replace the old software which a new one that would make handling court procedures more efficient and more user friendly
  • Changing laws and requirements
  • And last but not least the imminent Y2K problem (anybody remember≡ƒÿë)

Using Visual Objects was an obvious choice at that time and has proven to be the right decision over the years.

The first official version of EurekaFach was released in the year 1998. It is interesting to note that this version is 20 years later still in use at some courts although these installations will be replaced by the .Net version in the near future.

Fast forward to 2018. In this year, the development of EurekaFach .Net started as a migration project. It was finished two years later.

EF MainWindow 

Fig: 1: EurekaFach .Net shows (faked) core details of all legal documents currently in the database

Since Visual Objects was no longer developed at this time, X# as a VO compatible language that was based on the .Net runtime was an obvious choice for several reasons:

  • One reason for the trust in X# was, besides the highly experienced developer team with Robert, Chris and others, the fact that X# is based on the Roslyn compiler platform. This means that the X# compiler uses the same code generator that Microsoft own languages C# and Visual Basic use. Therefore, one could assume that all the language features of C# would also be available with X# sooner or later (most of the time sooner).
  • Although porting a large VO application that was developed in the 90ties to a complete new platform about 20 years later could seen as the "golden chance" to completely rework the architecture of the application it was decided to keep the 2-tier design with a GUI frontend and a database server as the backend. No middleware, no MVC or MVVM and no dependency injection and other design patterns to think (and worry) about.

Keeping the same old architecture for the new application was one the main reasons the migration project could be finished on time and within the budget. Otherwise, the migration project would have turned into a complete new project with the likely probability of not ending with a happy end.

Nevertheless, there were still a couple of delicate issues to decide:

  • How to access the database? Since VO2Ado for .Net was not ready when the migration started, an alternative was needed.
  • How to deal with the completely offline nature of database access in .Net?
  • How to keep the datalayer agnostic to a certain DBMS?
  • WinForms or WPF for the GUI?
  • Keep the VO runtime functions or replace them with .Net runtime functions if possible?
  • How to replace VO2Ado, bBrowser and Report Pro?

To make a long story short for all these questions good answers were found. The following short description of the answers to each of the listed challenges should help other developers in the community in their decission process if they are about to migrate a large VO application to .Net.

.NET classes instead of VO2Ado

Since using VO2Ado for database access was not an option the complete database layer (DAL for short) was written from scratch and put in a separate "DAL classes" and also in a "DAL project" that is used by several other projects as well. This was by far not as much work as it may sound. The DAL classes consist of several methods that for example opens a connection to a database, run select queries that either return a DataReader, a DataTable or a single value or run a SQL command that updates the database.

All the databinding with the UI components is done through the datasource property of that component. The datasource property is assigned either a DataTable or a BindingSource component that has its own datasource property.

Query and forget - keep the data in the database

One of the major differences, if not the major difference, between the old datacentric world of VO and the world of the .Net Framework is the complete offline nature of the later. This means that once that data had been queried by a Select statement through a DataReader or a DataAdapter there is no connection to the database anymore. Query and forget.

This is not a problem at all if the data is only used in a read only or look up scenario. It can be challenging though if the data is updated inside the UI, for example in a data grid, and has to be written back to the database.

Writing the data back is just a matter of generating the needed Insert-, Update- and Delete-statements every time. That is easy to solve. With a few exceptions EurekaFach .Net completely relies on SQL statements as strings. Parameters are included in the SQL string either by string concatenation or with the help of the new string interpolation feature of X#, which is very convinient. Another great feature of the recent X# compiler versions is how easy it has become to include aliases inside a SQL query (see Listing 1).

 sqlText := "Select Nummer ""Nummer"",Bez ""Bez"",AzStamm.Buchstabe ""Buchstabe"","
sqlText += "Maske ""Maske"",Zaehlkarte ""Zaehlkarte"", Verteilart ""Verteilart"","
sqlText += "Turnus ""Turnus"",Verfart ""Verfart"" "
Self:taAzStamm := DbFunctions:InvokeSelect(sqlText)
Self:bsAzStamm := BindingSource{}
Self:bsAzStamm:DataSource := Self:taAzStamm
Self:gridControl1:DataSource := Self:bsAzStamm

Listing 1: SQL Select query and databinding to a Grid Control

It can get complicated though when the data that should be updated with a SQL update statement had been changed in the meantime by another user. Just executing the update command would mean that all changes made by the other user since the time the data was queried would be overwritten with the new data. Usually that is not exactly the behavior that users want.

The way .Net handle this situation is called optimistic concurrency and is described at epic length in the official ADO.Net documentation and in countless articles on the web. It means that for each field the old and the new value of that field is included in the where clause of the update statement. If another user has changed the value of a field in the row that is about to be updated the where clause is not satisfied because the old value of that field from the time the data was queried is not the same as the new value of that field in the database. The consequence: the update statement will fail with a DBConcurrencyException and the data in the database is not affected.

Of course, this only delegates the problem back to the developer who would have to catch the resulting exception and figure out a clever way to decide if the value in the database should be kept or overwritten.

To make another long story short EurekaFach .Net uses a simple solution for this problem. It completely relies on the fact that a such situation can never happen because any data that had been changed in the UI is immediately written back to the database and the last update always wins. Although it is debatable if this is, really a perfect solution or not it was proven a solid solution during the years EurekaFach .Net is in use.

One set of classes to rule them all

One of the main requirement of EurekaFach .Net was that it has to be DMBS agnostic likes it's predecessor. This was accomplished by using the classes in the namespace System.Data.Common. These classes uses a factory pattern for providing a provider agnostic database access. The only requirement is that the database provider has to be configured within either the config file of the application or the machine.config file of the .Net runtime (Listing 2).

 var adapter := EFDbFactory:CreateDataAdapter() 
adapter:selectCommand := (DbCommand)selectCommand
adapter:selectCommand := sqlText
var ta := DataTable{}
adapter.fill(ta)

Listing 2: Filling a data table with a query result by using provider independent classes

Using the classes in System.Data.Common does not mean of course that the .Net runtime takes care of DMBS specific differences. This still is the responsibility of the developer. There were two occasions where provider specific adjustments had to be made in EurekaFach .Net: When fetching long values from an Oracle database and explicit type conversion between bool and int types for a PostgreSQL database. Everything else works perfectly.

Another problematic issue can only be touched briefly: Open connections. Although connection pooling is active per default in some occassions the number of open connections grew and grew. This is not a big problem with SQL Server but Oracle and PostreSQL are stricter. The reason for this "leak" were datareaders that where not used inside a Begin Using/End Using block (which is the recommend way). The solution was to explicitly close the datareader as soon as they were no longer needed. Sounds simple but sometimes hard to accomplish in a class where a "global" datareader is used inside several methods. So better use datareaders only locally and use a datatable as a "global" record store when there is no better alternative because the .Net runtime takes care of the connections.

WinForms, of course

WinForms is the short term for the classes in the namespaces System.Windows.Forms and System.Drawing. All the graphic output is based on GDI+ which is the Windows graphic library developed by Microsoft that is an enhancement of the basic GDI-API of the Win32 API.

Although the Windows Presentation Foundation (WPF) was already a part of the .Net Framework when the migration project started it was never considered as an option for several reasons:

  • The improvements of WPF like a XML based UI definition, advanced databinding capabilities and animations would not benefit the application.
  • WinForms is solid, fast and rich of functionality. There is very good support by all third party component vendors.
  • The WinForms application modell resembles more the familiar VO model than WPF.
  • In the end, learning WPF would have been too much effort and little or no gain at all for the project.

Excurse - the power of modern third party GUI components

EurekaFach already used third party components like the CodeJock UI components for the ribbon and the Tx Text Control as a rich textbox for editing text with all the formatting options that users already are used too. For the EurekaFach .Net project the decision was made for the DevExpress WinForms UI components. Although companies like ActiPro, ComponentOne, Infragistics, SyncFusion, Telerik and others offers such products of high quality as well, DevExpress stands above the competition because of the rich functionality of their UI components, especially the GridControl of course, and it's outstanding support that answers technical questions usually within a day or two without any service aggrement or other requirements.

Replacing bBrowser with the DevExpress GridControl

The advanved capabilities of the GridControl was one of the reasons that EurekaFach .Net did not need a replacement for bBrowser (and also ReportPro). The ability to customize a grid through filters and conditional formating in combination with a print preview and advanced printing capabilities can be activated and customized with very little coding.

 EF GridControl PrintPreview

Fig 2: The print preview of the Grid Control offers the same printing capabilities of a report designer

 EF GridControl PrintPreview DocumentExport

Fig 3: The print preview also offers a document export

 

Fig 4: Customizing the Grid Control with formatting rules based on cell values

It is still amazing after all these years how easy it has become for developers to provide functions that in the past used to be only available in big office applications like Microsoft Excel and Microsoft Word with such little effort. In EurekaFach .Net, users can customize query filters inside the grid control and highlight filtered rows with individual formating that is automatically saved in the registry so that it can be applied again in the future. Implementing such functionality through coding would have taken months in the past if it had been possible at all.

VO runtime or .Net?

The old VO runtime functions can be used 1:1 within an X# project when the project dialect is "Visual Objects". There is no need to replace an AllTrim() function with a trim()-method, an Upper()-function with a toUpper()-method or a CTod function with Datetime.Parse(). On the contrary. Deliberately replacing a Instr() function with a substring()-method just for the sake of "modernization" can be real dangerous because the two might look they would work similiar but in fact are complete different. Some lessons can only be learned the hard way🙁.

 EF ProjectDialect

Fig. 5: For the dialect, "Visual Objects" was the obvious choice

Allthough the use of the .Net runtime function is encouraged when adding new functionalitay all the VO runtime functions can be used without having to change something. This is also true for the immediate window during debugging with two notable exceptions: The colon (:) has to be replaced with a dot and the index for arrays and lists always starts at 0. And one more thing: All the syntax is case sensitive😉 so it's recommend not to use different cases for a variable name in X#.

 EF ImmediateWindowCaseSensitive

Fig 6: The immediate windows prefers C# syntax

Although it is recommend to use generic Lists (like List<T> where T stands for a type) instead of arrays for performance reasons the VO arrays can be used 1:1 in X# of course. Modern language features of C# like LINQ queries or anonymous types are fully supported by X# but the good old AScan()-function is still a powerful query function.

Seperation of concerns

It was noted in the begining of this overview that EurekaFach .Net is, like its predecessor, based on a classic 2-tier application modell. This does not mean though that the application is one monolythic block. First, the Visual Studio solution consists of several projects that could be used as building blocks together with other projects. Second and more important EurekaFach uses a strict separation between UI classes and classes that implement the logic behind a window or dialog. All window and dialog classes are implemented in a C# project. All window and dialog classes in the main x# project inherit from the C# classes. Whereas the C# classes only contain the class definitions and the code created by the WinForms designer all the other code, including the event handlers, is implemented in the X# class.

There were several reasons for this "separation of concerns". The most important reason was that the WinForms designer in C# was much better than the X# one when the migration project started.

A few metrics about the project

Since the code metrics analyzer in Visual Studio does not work with X# projects, we had to use either a tool like NDepend or write a script for simple "total lines for codes" metrics. A PowerShell script did a rough analysis of the source code by counting prg files, class definitions and lines that were not a comment.

Number of

Zahl

projects

18

prg files

455

C# files

65

class definitions

588

lines of code (without comments)

160278

windows and dialog boxes

165

database tables

268

Table 1: A few (estimated) metrics about EurekaFach .Net

Summary

The migration of EurekaFach to EurekaFach .Net was a success on many levels. It was completed on time and within the budget. Several different ingredients were part of the "sucess formula":

  • The rock solid and fast X# compiler and the VO runtime functions
  • The very good X# extension for Visual Studio (although with room for improvements within the code editor)
  • The outstanding support through the X# team (thanks to Robert, Chris and other X# developers)
  • The decision to keep the development project as a pure migration project and not change the architecture for example
  • Using WinForms instead of WPF because it kept migrating the VO code simple
  • The fact that EurekaFach was a rock solid application with a rich functionality that had been in use by thousands of users for many years
  • The outstanding functionality of the DevExpress UI components especially the Grid Control that provides a lot of built in comfort for the users and makes the developer life really joyfull≡ƒÿë

We hope, that all these points are helpful for other developers who might still have large VO applications that face a "end of life" sentence somewhere in the future.

We are happy to answer questions about the EurekaFach migration project. Please contact us through This email address is being protected from spambots. You need JavaScript enabled to view it..


No comments