Archiv der Kategorie: Programmierung

C# .NET : Collections im .NET Framework

Intention

Eines der wichtigsten .NET Elemente zum Verwalten vom Datenbeständen im Speicher sind Collections (Auflistungen). Im Vergleich zu normalen Array-Typen bieten diese die Möglichkeit zur Laufzeit Objekte hinzuzufügen, ohne vorher die Größe/die Anzahl der Objekte in der Collection zu kennen. Collections bieten Funktionen zum Hinzufügen, Entfernen und Suchen/Finden von Objekten. Ist ein Objekt in einer Auflistung erstmal gefunden, kann dieses über die Objektreferenz auch direkt in der Auflistung geändert werden.

Typsicher
  • Bessere Leistung
  • keine explizite Umwandlung notwendig um auf Objekteigenschaften zuzugreifen
  • Akzeptieren beim Erstellen einen Typparamter <T>
  • Unterstützung für Windows-Store-Apps
Typsicher…
Generische Auflistungen
Generische Auflistun…
Nicht
generische Auflistungen
Nicht…
Auflistungen
(Collections)
Auflistungen…
Nicht typsicher
  • Speichern Elemente als Objekt (Object)
  • erfordern explizite Umwandlung in den Objekttyp um auf Objekteigenschaften zuzugreifen
  • keine Unterstützung für Windows-Store-Apps
Nicht typsicher…
System.Collections.Concurrent
System.Collections.Concurrent
System.Collections
System.Collections
System.Array
System.Array
System.Collections.Generic
System.Collections.Generic
Threadsicher
Threadsicher
Findet man oft in älterem Code
Findet man oft…
System.Collections.Immutable
System.Collections.Immutable
NuGet-Paket
NuGet-Paket
Actor
Actor
Hinzufügen
Hinzufügen
Ändern
Ändern
Entfernen
Entfernen
Suchen
Suchen
        Collection
  1. Object 1
  2. Object 2
  3. Object 3
  4. Object n
Collectio…
«interface»
 System.Collections.IEnumerable
«interface»…
foreach(Object o in Collection) 
{
  o.Property…
}
foreach(Object o in Collectio…
«interface»
 System.Collections.Generic.IEnumerable
«interface»…
LINQ
var
query = from Object o in Collection
where o.Attribute > 95
select o;

foreach (Object o in query) {
Console.WriteLine(o.Attribute + „“
);
}
LINQ…
Viewer does not support full SVG 1.1

Auflistungen implementieren das Interface „IEnumerable“, um das Iterieren durch die Objekte in der Liste zu ermöglichen. Die foreach-Schleife nutzt beispielsweise dieses Interface um durch alle Objekte einer Collection zu iterieren.

Über die Abfragesprache LINQ (Language Integrated Query) lassen sich SQL-ähnliche Abfragen auf Collections durchführen,

Namespaces / Namensräume

Der Namensraum für .NET Framework Collections liegt unter System.Collections.*, wobei weitere Sub-Namensräume existieren.

  • System.Collections.Concurrent (mehrere Threads / Tasks können parallel auf diesen Collections im Speicher operieren)
  • System.Collections.Immutable (man arbeitet hierbei nur auf Kopien / die ursprünglichen Daten werden nicht geändert – muss zusätzlich über NuGet-Paket installiert werden)
  • System.Collections.Generic

Dynamische Strukturen/Collections allokieren immer 2^n Speicher-Plätze

Die Property „Capacity“, welche an jeder Collection anhängt, zeigt die Anzahl der Speicherplätze, die die Collection intern als Array alloziert hat. Bei 1025 Elementen werden intern 2048 Plätze vorbereitet. Bei 2049 Elementen werden intern 4096 Plätze vorbereitet.

Microsoft SQL Server: How-to realize a SQL Statement that only returns the maximum or the minimum rows of a group (similar to an non-existing aggregate function for the GROUP BY clause)

Actual situation

A change request (field „pcr“) only can have one unique assigned user that shall be informed about the assignment every night.

The assigned user (field „created_by“) of a change requests (field „pcr“) is changing several times a day. Every time the user (field „created_by“) changes to another user, a table entry with the actual time stamp (field „created_on“) is inserted to a SQL table.

At the end of the day, the system shall report via email the users that have been assigned to a PCR (only one user per change request).

The following table contains entries with people wo shall be informed every evening.

idpcrcreated_oncreated_by
1PCR-12020-02-26 09:20:52.977user1
2PCR-12020-02-26 09:20:54.667user1
3PCR-22020-02-26 09:20:57.137user1
4PCR-22020-02-26 09:20:59.003user1
5PCR-22020-02-26 09:21:07.540user3
6PCR-32020-02-26 09:21:09.850user3
7PCR-42020-02-26 09:21:12.850user3
8PCR-42020-02-26 09:21:15.100user3
9PCR-52020-02-26 09:21:55.323 user3
10PCR-22020-02-26 09:22:06.037user2
11PCR-52020-02-26 09:22:07.037user2
12PCR-72020-02-26 09:22:08.760 user2
13PCR-72020-02-26 10:20:07.233user2
14PCR-82020-02-26 10:20:08.967user2
15PCR-82020-02-26 10:20:13.393user1
16PCR-92020-02-26 10:20:15.020user1
17PCR-72020-02-26 10:20:19.497user3
18PCR-92020-02-26 10:20:20.163user3

A nightly executed batch job (at 23:59h every evening) shall provide the possibility to inform user1, user2 or user3 about their assigned PCR’s. Only the latest entry per PCR, that can be recognized by the timestamp (field „created_on“) represent the user assigned user at the end of the day

Problem

The SQL Statement shall output the latest entry per assigned user of each PCR. With a standard aggregate function this is not possible because the whole row entry has to be retrieved.

Approach

The Microsoft SQL Server has a proprietary function RANK(), that prints out the ranking of the PCR entry in connection with PARTITION BY and ORDER BY. The ORDER BY has to be used DESC, so that the latest entry always is on rank 1.

Because this methods only can be used within the SELECT statements fields and not withing WHERE, we need a second parent query to select everything with rank 1.

Solution

SELECT *
FROM (
	SELECT	id, 
			pcr,
			created_on, 
			created_by,
			RANK () OVER ( 
				PARTITION BY pcr
				ORDER BY created_on DESC
			) as biggestHasRangOne
	FROM nightly_email
)tab 
WHERE biggestHasRangOne=1 
AND CONVERT(date, GETDATE())=CONVERT (date, created_on)
Only the latest PCR assignment has been selected for that day.

To get the smallest one (minimum) in for that day you have to use

ORDER BY created_on ASC

In the RANK() – Partition by -Syntax.

Python: Getting started with Python

Intention

Since JAVA has been overtaken by Oracle, it can’t be mistaken to get skilled with the basic concepts of Python. So this is my short Getting Started tutorial with my personal conclusion.

Instead of getting annoyed about the glorification of Python, it would be better to spend some time to have a short look at this programming framework.

In the most cases a language itself is not the crucial point, but it’s what it’s framework is providing for the developer.

So the most popular thing we hear about is the capabiliy that Python is good for…

  • Data Science
  • Arteficial Intelligence (especially the library Tensor flow)

Installation

To install Python, you have to go to https://www.python.org/downloads/ and download and install Python. The website is clearly arranged and you don’t have to spend much time to search for the correct runtime according to your needs.

After you have downloaded Python, a installation wizard guides you through the installation process in two steps. It catches to my eye that there are not so much options to choose except for the folder where you want to install it.

Getting started

So what do we need now… a development environment? Hmm… well because I have installed a Visual Studio 2013, i want to test the free „Python support for Visual Studio 2013), which can be found for different Visual Studio versions here:

https://github.com/Microsoft/PTVS/releases/v2.2.2

Python Tools for Visual Studio 2013 can be downloaded from GitHub

After the installation, there is a new Project Type available, when choosing

Visual Studio 2013 menu: File –> New Project

A new Python menu appears on the left side and we can choose to create a console application

After that you can immediatly start to code Python and press the Start-Button. Here is the „Hello World!“-Program:

A „Hello World!“-Program just consists one command.

What is a little bit weird is, that it doesn’t seems to matter if you use the following Syntax instead of the function-based print:

# This Python comment is like a UNIX Shellscript comment
print "Hello world!" # Is it possible to append a comment to the end?

# Is this really clean code if it doesn't matter how you write it?
print ("Hello world!") 

# How do you write multi line?
print ("Hello "
"world!") # this works without line break

print "Hello "
"world!" #this not

print """Hello 
 world!""" #this works but shows the line break

# without declarion of a variable
print "Number 1:";
x = input(); # My first Input 
print "Number 2:";
y = input("Here you can enter the input prompt:"); # My next Input 
print """

The result is:
==============
"""

print "The result is " + str(x + y) # working
# Python is not converting 
#automatically like C# when concatenating an Int to a String

print x #works
print y #works
print "A string for x: " + str(x) +"" #working 
print "A string for y: " + y +"" #not working 
#because he thinks that y is an Integer

In console applications it is possible to work simply with input and print. By experimenting a while you can find out what is working and what is not…
An input like „2“ will be automatically converted as an integer type (when it only contains an integer). It is possible to print the integers using the function (or command) „print“, but it is not possible to print an integer concatenated to a string.

My first conclusion

„Wenn Sie Python sehen wollen, dann gehen sie doch ins Dschungelcamp!“

Nico Gerbig in WhatsApp

For non programmers it seems to be really easy to write small console programs, but the language itself allows much syntax variants that i don’t would expect as clear readable code (especially in Python 2.7 what i have been used ).

But as shown in the following Screenshot newer python versions are a little bit more strict concerning procedure-based-programming.

In newer Python versions the BASIC-like command syntax is replaced by a real procedure syntax.

As you can see above, there is a small onboard IDE shipping with python that has a console in which it is possible to execute python code directly. Additionally it allows you to write programs in whole Python files by selecting the „File->New File“ in the menu.

The IDE can be found in the Start menu after installing a
Python package

One thing that makes me muse about the language concept is the missing option for variable declaration. Learing tutorials and guides are always promoting the omission of type-safe variable declaration as innovative concept and benefit in comparison to other common programming languages. I think it would be eligable to ask the question: „Why do non type-safe languages like JavaScript need a type-safe extension like TypeScript?“. Languages like Visual Basic (for applications) have introducted the „option explicit“ command to force the developer to do this … why? 🙂

Next steps

In further steps i want to find out how to point my Visual Studio to the newer Python framework. Python 3.8 is already installed but i do not have the choice to change it in Visual Studio. So i guess there must be a seperate configuration for this.

I am looking forward to evaluate the Tensorflow AI library and what benefit i can get from it.

Visual Basic und VBA: Dynamische String Array / Dynamic string array in VBA

Problem

In VBA soll ein dynamisches String-Array verwendet werden.

Solution – Lösung

Array initialisieren:

      Dim cbValuesStringArray() As String

      While i<10
        i = i + 1
        ReDim Preserve cbValuesStringArray(i - 1)
        cbValuesStringArray(i - 1) = CStr(i)
      End While

Array auslesen:

    For j = 0 To UBound(cbValuesStringArray)
        Debug.Print CStr(j) & " - " & cbValuesStringArray(j)
    Next j

C# + Reguläre Ausdrücke / Regular Expressions / Progress Tags : Alle Vorkommnisse zwischen einem Start-Teilstring und End-Teilstring (z.B. bei HTML Tags) finden und verarbeiten / Find all occurencies of start and end tag and progress them

Problem

Es sollen alle Vorkommnisse eine Start- und End-Tags gefunden werden und der Text dazwischen verarbeitet werden.

Ansatz – Approach

Verwendung von regulären Ausdrücken:

Regex.Matches findet alle Auftreten anhand eines Patterns, was den Regulären Ausdruck definiert:

(diagram://{[^>]+})

Eine Funktion string replaceDiagramAndElementLinkURLs(string eaNoteString) baut einen neuen String zusammen und schickt ihr wieder zurück.

Lösung – Solution

Im folgenden Beispiel gibt es in einem String mehrere Vorkommnisse des Start-Tags „$diagram://{“ und dem End-Tag „}“.
Zwischen dem Diagramm steht eine Nummer (guid) die an eine aspx-Seite übergeben werden soll.

Z.B. lautet der String

string verarbeiten = @"
<html>
...
Dies ist ein Diagramm: <a href="$diagram://{1234465}">Link 1</a> hier steht noch 
ein Diagramm: <a href="$diagram://{3455565}">Link 2</a> und das führt sich fort..
...
</html>
";

und nach dem Verarbeiten ist der Inhalt:

string verarbeiten = @"
<html>
...
Dies ist ein Diagramm: <a href="Level2Process.aspx?map=1234465">Link 1</a> hier steht noch 
ein Diagramm: <a href="Level2Process.aspx?map=3455565">Link 2</a> und das führt sich fort..
...
</html>
";

Dazu kann man folgenden Regulären Ausdruck verwenden:

    public static string replaceDiagramAndElementLinkURLs(string eaNoteString)
    {
        string neuerString = eaNoteString;
        string pattern = @"(diagram://{[^>]+})";

        MatchCollection matches = Regex.Matches(neuerString, pattern);

        if (matches.Count > 0)
        {
            foreach (Match m in matches)
            {
                string toReplace = "$" + m.Groups[1].ToString();
                string guid = toReplace.ToString().Replace("$diagram://", "");

                neuerString = neuerString.Replace(toReplace, "Level2Process.aspx?map="+guid );
            }
        }
        return neuerString;
}

Sparx Systems Enterprise Architect: Get Images of Diagram By Diagram Name SQL

Problem

The Images of a specific diagram in the data structure of the Sparx Systems Enterprise Architect should be read by diagram name.

Approach

Usage of MDB Plus and Data Mining

Solution

This is SQL for the Access / .eap-File – it should be rewritten for other SQL Servers (i.e. the brackets can be removed and Functions like InStr/Mid shall be replaced)

SELECT	dia.Name As Diagram,
		IIF(Trim(objstart.[Name]) = 'Text', 'Text', objstart.stereotype) As stereotype, 
		diaobj.RectLeft As x,
		diaobj.RectTop As y,
		diaobj.RectRight-diaobj.RectLeft As Width,
		Abs(diaobj.RectBottom-diaobj.RectTop) As Height,
		objstart.Object_ID,
		IIF(Trim(objstart.[Name]) = 'Text', 'Text-'& objstart.Object_ID ,objstart.Alias) As [key],
		IIF(objstart.[Name] = 'Text', objstart.Note, objstart.[Name]) As phaseName,
		objstart.[ea_guid] As [guid],
		diaobj.ObjectStyle,
		IIF(
                    InStr(diaobj.ObjectStyle, "ImageID")>0, 
                    Mid(diaobj.ObjectStyle, InStr(diaobj.ObjectStyle, "ImageID")+8 , Len(diaobj.ObjectStyle)- (InStr( diaobj.ObjectStyle, "ImageID")+8) ),
                    ''
        ) As ImageId     
FROM
((
		[t_diagram] dia LEFT JOIN (Select Diagram_ID, Object_ID, RectLeft, RectTop, RectRight, RectBottom, ObjectStyle from [t_diagramobjects]) diaobj ON dia.[Diagram_ID]=diaobj.[Diagram_ID])
LEFT JOIN [t_object] objstart ON objstart.[Object_ID]=diaobj.[Object_ID])
WHERE objstart.Object_Type IN ('Text','Boundary') AND IIF(InStr(diaobj.ObjectStyle, "ImageID")>0, 
                                                                Mid(diaobj.ObjectStyle, InStr(diaobj.ObjectStyle, "ImageID")+8 , 
                                                                Len(diaobj.ObjectStyle)- (InStr( diaobj.ObjectStyle, "ImageID")+8) ),
                                                                '') <> ''
AND dia.Name='0' 
ORDER BY 12 DESC,1,2,3,4,5,6,7,8,9       

Sparx Systems Enterprise Architect SQL: Get all Images with ImageID of a diagram

Problem

All Images of an Diagram (the ImageIds) shall be determined, so that can be read out from the table t_image (see previous article about BLOB and EA).

Approach – Ansatz

Usage of the tables
– t_diagram
– t_diagramobjects
– t_object

Solution – Lösung

SELECT	dia.Name As Diagram,
		IIF(Trim(objstart.[Name]) = 'Text', 'Text', objstart.stereotype) As stereotype, 
		diaobj.RectLeft As x,
		diaobj.RectTop As y,
		diaobj.RectRight-diaobj.RectLeft As Width,
		Abs(diaobj.RectBottom-diaobj.RectTop) As Height,
		objstart.Object_ID,
		IIF(Trim(objstart.[Name]) = 'Text', 'Text-'& objstart.Object_ID ,objstart.Alias) As [key],
		IIF(objstart.[Name] = 'Text', objstart.Note, objstart.[Name]) As phaseName,
		objstart.[ea_guid] As [guid],
		diaobj.ObjectStyle,
		IIF(
                    InStr(diaobj.ObjectStyle, "ImageID")>0, 
                    Mid(diaobj.ObjectStyle, InStr(diaobj.ObjectStyle, "ImageID")+8 , Len(diaobj.ObjectStyle)- (InStr( diaobj.ObjectStyle, "ImageID")+8) ),
                    ''
        ) As ImageId     
FROM
((
		[t_diagram] dia LEFT JOIN (Select Diagram_ID, Object_ID, RectLeft, RectTop, RectRight, RectBottom, ObjectStyle from [t_diagramobjects]) diaobj ON dia.[Diagram_ID]=diaobj.[Diagram_ID])
LEFT JOIN [t_object] objstart ON objstart.[Object_ID]=diaobj.[Object_ID])
WHERE objstart.Object_Type IN ('Text','Boundary') AND IIF(InStr(diaobj.ObjectStyle, "ImageID")>0, 
                                                                Mid(diaobj.ObjectStyle, InStr(diaobj.ObjectStyle, "ImageID")+8 , 
                                                                Len(diaobj.ObjectStyle)- (InStr( diaobj.ObjectStyle, "ImageID")+8) ),
                                                                '') <> ''
AND dia.Name='{PutInYourDiagramNameHere}' 
ORDER BY 12 DESC,1,2,3,4,5,6,7,8,9    

Sparx Systems Enterprise Architect SQL : Query to get the order of objects / elements in the project browser tree

Problem

The order of tree elements in the project browser should be queried in SQL.
Die Reihenfolge der Objekte im Projekt-Browser soll über SQL abgefragt werden

Approach – Ansatz

Usage of the TPos column within the tables t_object and t_package.
Verwendung der TPos Spalte in den Tabellen t_object und t_package.

Solution – Lösung

SELECT b.TPos as Package_Position, 
       b.Name as Package_Name, 
       a.TPos as Object_Tree_Position, 
       a.Object_ID, 
       a.Name as Object_Description
FROM t_object a INNER JOIN t_package b ON a.Package_ID=b.Package_ID 
WHERE Stereotype='Process Step'
ORDER BY 1,2,3