<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Yet another developer journey ...]]></title><description><![CDATA[Yet another developer journey ...]]></description><link>https://blog.sigterm.eu</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 03:09:23 GMT</lastBuildDate><atom:link href="https://blog.sigterm.eu/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Empty string and array best practices in C#]]></title><description><![CDATA[Just a very short blog post... for everyone who is not yet known to it. Since .Net Framework 4.6 for two immutable types we got new static fields in the framework:

Array.Empty<T>

string.Empty


// instead of
string foo = "";
byte[] bar = new byte[0...]]></description><link>https://blog.sigterm.eu/empty-string-and-array-best-practices-in-c</link><guid isPermaLink="true">https://blog.sigterm.eu/empty-string-and-array-best-practices-in-c</guid><category><![CDATA[C#]]></category><category><![CDATA[string]]></category><category><![CDATA[Strings]]></category><category><![CDATA[arrays]]></category><category><![CDATA[array]]></category><category><![CDATA[#empty]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Sat, 01 Jun 2024 18:37:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/tQ64LAblOUU/upload/ea96bec89a294f5a4533da414e45fb3e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Just a very short blog post... for everyone who is not yet known to it. Since .Net Framework 4.6 for two immutable types we got new static fields in the framework:</p>
<ul>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.array.empty?view=netframework-4.6">Array.Empty&lt;T&gt;</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.string.empty?view=net-8.0">string.Empty</a></p>
</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-comment">// instead of</span>
<span class="hljs-keyword">string</span> foo = <span class="hljs-string">""</span>;
<span class="hljs-keyword">byte</span>[] bar = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">0</span>];

<span class="hljs-comment">// prefer</span>
<span class="hljs-keyword">string</span> foo = <span class="hljs-keyword">string</span>.Empty;
<span class="hljs-keyword">byte</span>[] bar = Array.Empty&lt;<span class="hljs-keyword">byte</span>&gt;();
</code></pre>
<p>If you are now asking yourself why you should use this - string and array are immutable (they will always be created new when the content does change and the old memory is garbaged). By using the static fields there is no additional memory location for the value of the variable, it will always be the same.</p>
<p>Naturally, you will first note a real impact if you are creating very much strings and/or arrays. But it is always better to follow best practices from the beginning instead of running into problems afterwards...</p>
]]></content:encoded></item><item><title><![CDATA[Thread safety]]></title><description><![CDATA[Introduction
In one of my older projects, I often had to synchronize and work with different parallel threads. Using async, parallel or 'real' threads does not make a real difference when it is coming to thread safety.
As a very short short instructi...]]></description><link>https://blog.sigterm.eu/thread-safety</link><guid isPermaLink="true">https://blog.sigterm.eu/thread-safety</guid><category><![CDATA[thread safety]]></category><category><![CDATA[Threads]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Wed, 29 May 2024 17:31:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FQzGa9FLgE0/upload/72d872fd0b0d917175b4cf63d6179318.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>In one of my older projects, I often had to synchronize and work with different parallel threads. Using async, parallel or 'real' threads does not make a real difference when it is coming to thread safety.</p>
<p>As a very short short instruction to thread safety: Every value is stored in memory somewhere, somehow. The location in memory has got an address, so called <a target="_blank" href="https://en.wikipedia.org/wiki/Memory_address">memory address</a>. When you set the value once and only read from it in the rest of the program you won't have any problems (e.g. const). But if you set the value multiple times and read from it, you do not know which result you will get as all threads are accessing the same memory address at the same time.</p>
<p>Let us take an example, you have a string in memory containing '1234567890' and re-writing this the whole time to '0987654321'. It does require time to set the value in memory and reading is much faster. When you read this value in parallel from another thread you will never know which value you get. It may also happen that you get 'garbage'.</p>
<p>This article does only cover handling variables not the program flow itself. When working in parallel, always make sure that all parts of your application or area can be handled parallel (ServiceProvider / external resources).</p>
<h3 id="heading-integer">Integer</h3>
<p>Integers can be implemented quite simple using <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked?view=net-8.0">Interlocked</a> and the corresponding methods.</p>
<p>The main method I mostly work with is <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked.exchange?view=net-8.0">Exchange()</a>, please just take a look at the ThreadSafeBool class further down.</p>
<h3 id="heading-boolean">Boolean</h3>
<p>Following just a short dump of a thread safe bool class implemented using <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked?view=net-8.0">Interlocked</a>.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ThreadSafeBool</span>
    {
        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;summary&gt;</span> internal storage <span class="hljs-doctag">&lt;/summary&gt;</span></span>
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> _internalBackingDoNotUse;

        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;summary&gt;</span> Use interlock exchange for thread safety <span class="hljs-doctag">&lt;/summary&gt;</span></span>
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span> ThreadSafeBoolValue
        {
            <span class="hljs-keyword">get</span> =&gt; Interlocked.CompareExchange(<span class="hljs-keyword">ref</span> _internalBackingDoNotUse, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>) == <span class="hljs-number">1</span>;
            <span class="hljs-keyword">set</span>
            {
                <span class="hljs-keyword">if</span> (<span class="hljs-keyword">value</span>) Interlocked.CompareExchange(<span class="hljs-keyword">ref</span> _internalBackingDoNotUse, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>);
                <span class="hljs-keyword">else</span> Interlocked.CompareExchange(<span class="hljs-keyword">ref</span> _internalBackingDoNotUse, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>);
            }
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">bool</span> <span class="hljs-keyword">operator</span> <span class="hljs-title">true</span>(<span class="hljs-params">ThreadSafeBool tsb</span>)</span>
        {
            <span class="hljs-keyword">return</span> tsb.ThreadSafeBoolValue;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">bool</span> <span class="hljs-keyword">operator</span> <span class="hljs-title">false</span>(<span class="hljs-params">ThreadSafeBool tsb</span>)</span>
        {
            <span class="hljs-keyword">return</span> !tsb.ThreadSafeBoolValue;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ThreadSafeBool</span>(<span class="hljs-params"></span>)</span>
        {
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ThreadSafeBool</span>(<span class="hljs-params"><span class="hljs-keyword">bool</span> <span class="hljs-keyword">value</span></span>)</span>
        {
            ThreadSafeBoolValue = <span class="hljs-keyword">value</span>;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">implicit</span> <span class="hljs-keyword">operator</span> <span class="hljs-title">ThreadSafeBool</span>(<span class="hljs-params"><span class="hljs-keyword">bool</span> <span class="hljs-keyword">value</span></span>)</span>
        {
            ThreadSafeBool tsb = <span class="hljs-keyword">new</span> ThreadSafeBool
                {
                    ThreadSafeBoolValue = <span class="hljs-keyword">value</span>
                };
            <span class="hljs-keyword">return</span> tsb;
        }

        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;summary&gt;</span> </span>
        <span class="hljs-comment"><span class="hljs-doctag">///</span> operator for using retrieving</span>
        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;/summary&gt;</span></span>
        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;param name="tsb"&gt;</span><span class="hljs-doctag">&lt;/param&gt;</span></span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">implicit</span> <span class="hljs-keyword">operator</span> <span class="hljs-title">bool</span>(<span class="hljs-params">ThreadSafeBool tsb</span>)</span>
        {
            <span class="hljs-keyword">return</span> tsb.ThreadSafeBoolValue;
        }

        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;inheritdoc /&gt;</span></span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">Equals</span>(<span class="hljs-params"><span class="hljs-keyword">object</span> obj</span>)</span>
        {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">base</span>.Equals(obj);
        }

        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;inheritdoc /&gt;</span></span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">Equals</span>(<span class="hljs-params"><span class="hljs-keyword">bool</span> other</span>)</span>
        {
            <span class="hljs-keyword">return</span> ThreadSafeBoolValue == other;
        }

        <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;inheritdoc /&gt;</span></span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">int</span> <span class="hljs-title">GetHashCode</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">return</span> ThreadSafeBoolValue ? <span class="hljs-number">1</span> : <span class="hljs-number">0</span>;
        }
    }
</code></pre>
<pre><code class="lang-csharp">    [<span class="hljs-meta">TestClass</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ThreadSafeBoolTests</span>
    {
        [<span class="hljs-meta">TestMethod</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">TestMethod1</span>(<span class="hljs-params"></span>)</span>
        {
            ThreadSafeBool tsb = <span class="hljs-literal">false</span>;

            <span class="hljs-keyword">bool</span> currentValue = tsb;
            Assert.AreEqual(currentValue, <span class="hljs-literal">false</span>);

            <span class="hljs-keyword">if</span> (tsb)
                Assert.Fail();
            <span class="hljs-keyword">if</span> (tsb == <span class="hljs-literal">true</span>)
                Assert.Fail();


            tsb = <span class="hljs-literal">true</span>;
            currentValue = tsb;
            Assert.AreEqual(currentValue, <span class="hljs-literal">true</span>);

            <span class="hljs-keyword">if</span> (!tsb)
                Assert.Fail();
            <span class="hljs-keyword">if</span> (tsb == <span class="hljs-literal">false</span>)
                Assert.Fail();
        }
    }
</code></pre>
<h3 id="heading-lock">Lock</h3>
<p>Using the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock">lock statement</a> we can use a simple object as some kind of 'blocker'. As in, we use this object to synchronize our requests. It is required to ensure that all access to the variable is only done using the lock statement.</p>
<p>Following a short example with lock and a string by using properties ensuring the access to the variable only inside the lock:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">object</span> _sampleLockedStringLock = <span class="hljs-keyword">new</span> <span class="hljs-keyword">object</span>();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> _sampleLockedString = <span class="hljs-keyword">string</span>.Empty;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> SampleLockedString
    {
        <span class="hljs-keyword">get</span>
        {
            <span class="hljs-keyword">lock</span>(_sampleLockedStringLock)
            {
                <span class="hljs-keyword">return</span> _sampleLockedString;
            }
        }
        <span class="hljs-keyword">set</span> 
        { 
            <span class="hljs-keyword">lock</span>(_sampleLockedStringLock)
            {
                <span class="hljs-keyword">if</span> (_sampleLockedString == <span class="hljs-keyword">value</span>)
                    <span class="hljs-keyword">return</span>;

                _sampleLockedString = <span class="hljs-keyword">value</span>;
            }
        }
    }
}
</code></pre>
<h3 id="heading-aspnet-imemorycache">ASP.NET IMemoryCache</h3>
<p>For web projects a great thread safe alternative for caches is <a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-8.0">IMemoryCache</a>. Providing easy setter/getter and even expiration for the cache entries!</p>
<h3 id="heading-thread-safe-collections">Thread safe collections</h3>
<p>To round up, please also refer to <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/">thread safe collections</a> and the great article <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/when-to-use-a-thread-safe-collection?source=recommendations">when to use them</a>.</p>
<p>Do not forget, that the collection itself is thread safe, but not the content if you are storing reference types inside.</p>
]]></content:encoded></item><item><title><![CDATA[NyxSql Part III - WPF/MAUI/AvalonUI]]></title><description><![CDATA[In part III we take a closer look at where to upgrade our UserInterface from WindowsForms. As NyxSql was created as a learning project more than a decade ago, there is no MVVM or anything else implemented, which will make the upgrade more hard as the...]]></description><link>https://blog.sigterm.eu/nyxsql-part-iii-wpfmauiavalonui</link><guid isPermaLink="true">https://blog.sigterm.eu/nyxsql-part-iii-wpfmauiavalonui</guid><category><![CDATA[future user interface]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Mon, 05 Dec 2022 19:20:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670267924005/w0rnbryS9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In part III we take a closer look at where to upgrade our UserInterface from WindowsForms. As NyxSql was created as a learning project more than a decade ago, there is no MVVM or anything else implemented, which will make the upgrade more hard as the code is not decoupled from the UserInterface.</p>
<h1 id="heading-user-interfaces-overview">User interfaces overview</h1>
<p>At first, we take a general look at the several available UserInterfaces. There are naturally more, but these are the most popular imho. Web interface is no choice, as we require a direct connection to the databases.</p>
<h2 id="heading-wpf">WPF</h2>
<p>In my current job I am heavily working with WPF, so at least I got the knowledge to do a fast migration. 
We could for example change to WPF windows and host the windows forms controls inside the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.integration.windowsformshost?view=windowsdesktop-6.0">WindowsFormsHost</a>, migrate the windows step by step.
Up from .Net 5 there is support for WindowsForms and WPF in .Net. However the new cross platform chosen by Microsoft is based on Xamarin and called MAUI. 
I could not find any information, beside some dev blogs or questions on reddit/quora, which will give us an inside if WPF will be further developed or discontinued at some point.
But WPF is now OpenSource and released under the MIT license, so everyone can further develop it. As many business apps nowadays are based on WPF, we can estimate that it will be supported and working at least one more decade. </p>
<h2 id="heading-maui">MAUI</h2>
<p>This is the "new" cross-platform GUI for .Net announced back in 2020. In effect it is Xamarin merged into .Net 6. The official release was in March 2022. If you ever developed any apps for Android or iOS with Xamarin you will find yourself very comfortable in MAUI. </p>
<h2 id="heading-avalonui">AvalonUI</h2>
<p>OpenSource, MIT licensed, .Net cross platform UI. A great start is the <a target="_blank" href="https://avaloniaui.net/FAQ">FAQ</a>. In short: </p>
<ul>
<li>Developed by around 20 people as core team and according to the faq by 'hundreds of developers'</li>
<li>Started in 2013 under the name Perspect</li>
<li><a target="_blank" href="https://avaloniaui.net/Support">Enterprise support</a> possible 
It seems to be possible to <a target="_blank" href="https://github.com/AvaloniaUI/Avalonia/issues/2379">host winforms/wpf</a> controls in AvalonUI, but all links from this issue lead to 404.</li>
</ul>
<h1 id="heading-declaration-of-requirements">Declaration of requirements</h1>
<p>As we are porting a WindowsForms application to the new user interfaces, we have to think about the most important point of the application. NyxSql is a graphical interface for sql queries and database content. As databases normally contain many data the performant display of data in a grid is the main concern. Especially if a query will return hundreds of thousands of rows.</p>
<p>Furthermore, we will need to decide if it shall be cross platform or only windows. I will get some feedback on this topic and plan to continue with that series at the end of the month.</p>
]]></content:encoded></item><item><title><![CDATA[NuGet Package Manager - incorrect credentials]]></title><description><![CDATA[When using package manager with sources which require to authenticate yourself (e. g. internal sources or paid subscriptions), it may happen that you need to change your password or just entered the wrong credentials.
Now, it is kinda like 'evil', be...]]></description><link>https://blog.sigterm.eu/nuget-package-manager-incorrect-credentials</link><guid isPermaLink="true">https://blog.sigterm.eu/nuget-package-manager-incorrect-credentials</guid><category><![CDATA[Nuget]]></category><category><![CDATA[Credentials]]></category><category><![CDATA[login]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Wed, 09 Nov 2022 08:27:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/RVmk2WsWsjg/upload/v1667883453066/AOFxvYhdY.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When using package manager with sources which require to authenticate yourself (e. g. internal sources or paid subscriptions), it may happen that you need to change your password or just entered the wrong credentials.</p>
<p>Now, it is kinda like 'evil', because you do not get prompted again. The invalid credentials are saved and you are just lost seeing error messages the whole time.</p>
<p>Following solutions are available:</p>
<ul>
<li>Remove the source from Visual Studio, close, open, enter them again (works 2 of 4 times)</li>
<li>Go to Control panel - User Accounts - Manage your credentials and check if they are listed there (never had that...)</li>
<li>Update the credentials with dotnet: </li>
</ul>
<p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-nuget-list-source">list all</a> and update afterwards:</p>
<pre><code>dotnet nuget list source
dotnet nuget update source <span class="hljs-string">"&lt;source name&gt;"</span> -u &lt;username&gt; -p &lt;pass&gt;
</code></pre>]]></content:encoded></item><item><title><![CDATA[Current solution contains incorrect...error and no build?!?]]></title><description><![CDATA[When working with multiple workstations (workstation / laptop) due to pandemic, we suddenly experienced the following error when opening solutions:
Current solution contains incorrect configurations mappings. It may cause projects to not work correct...]]></description><link>https://blog.sigterm.eu/current-solution-contains-incorrecterror-and-no-build</link><guid isPermaLink="true">https://blog.sigterm.eu/current-solution-contains-incorrecterror-and-no-build</guid><category><![CDATA[no build]]></category><category><![CDATA[incorrect mappings]]></category><category><![CDATA[visual studio]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Tue, 18 Oct 2022 03:49:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/C6duwascOEA/upload/v1666064916184/t2uEYZHMYv.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When working with multiple workstations (workstation / laptop) due to pandemic, we suddenly experienced the following error when opening solutions:
<code>Current solution contains incorrect configurations mappings. It may cause projects to not work correctly. Open the Configuration Manager to fix them.</code>
Perhaps due to some different visual studio installation settings? </p>
<p>With a link to open the configuration manager. My thought was like 'Uh great, fix is directly there'. Sadly you can click whatever you want in the configuration manager the problem does not go away... Furthermore no build is carried out</p>
<p>The fix is like:</p>
<ul>
<li>Close Visual Studio</li>
<li>Open the projects solution file (.sln) with an editor of your choice</li>
<li>Search for: <code>GlobalSection(ProjectConfigurationPlatforms) = postSolution</code> </li>
<li>Delete ALL lines until <code>EndGlobalSection</code></li>
<li>Save</li>
<li>Open with Visual Studio again</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[NyxSql Part II - .Net project files]]></title><description><![CDATA[Intro
Within this article we will take a look at the upgrade project file and how it should look like : )
With .Net (Core), Microsoft introduced a much better formatted and usable project file than in previous versions. Sadly, the upgrade assistant a...]]></description><link>https://blog.sigterm.eu/nyxsql-part-ii-net-project-files</link><guid isPermaLink="true">https://blog.sigterm.eu/nyxsql-part-ii-net-project-files</guid><category><![CDATA[C#]]></category><category><![CDATA[project file]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Thu, 22 Sep 2022 17:52:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/ovgRb5WLWMQ/upload/v1663868083645/0uSa3qa0s.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-intro">Intro</h2>
<p>Within this article we will take a look at the upgrade project file and how it should look like : )</p>
<p>With .Net (Core), Microsoft introduced a much better formatted and usable project file than in previous versions. Sadly, the upgrade assistant and new projects had been a mess in the beginning (for creating the project files), but slowly it seems to get better.</p>
<p>At the end of this article, you can find an example of the Nyx project file after the upgrade. I am not posting it right here, because nobody likes to scroll over dozens of lines...</p>
<h2 id="heading-general">General</h2>
<p>When reformatting/extracting the project file, it is important to know about the different properties. So, if you find some which are unknown to you, just look it up using the MSDN and be happy that you learned something new! : ) *Sadly, right now F1 (=Open Help) is only usable on the root properties, so we have to look them up manually.</p>
<p>Especially when working in teams it is important to have a unique structure throughout all projects. Imagine you want to change some setting, and always must search the project file, if and where this setting is used.</p>
<p>The first thing I normally do is execute the auto-formatting on the file by pressing Ctrl + Alt + Enter. Another important thing, use commentary blocks for a better visual structure.</p>
<p>Normally I split the project file into two different blocks. The first one does contain properties that are valid/required for all projects and the second one which is different for each project.</p>
<h2 id="heading-the-first-general-block">The first, general, block</h2>
<p>The properties which are valid for all projects: `</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">"Microsoft.NET.Sdk"</span>&gt;</span>
    <span class="hljs-comment">&lt;!--
    fixed settings, same for every .net 6 project
    --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
        <span class="hljs-comment">&lt;!--general --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Company</span>&gt;</span>y0<span class="hljs-tag">&lt;/<span class="hljs-name">Company</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Copyright</span>&gt;</span>Copyright © 2022<span class="hljs-tag">&lt;/<span class="hljs-name">Copyright</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PackageLicenseUrl</span>&gt;</span>www.mit-license.com<span class="hljs-tag">&lt;/<span class="hljs-name">PackageLicenseUrl</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PackageProjectUrl</span>&gt;</span>www.myproject.com<span class="hljs-tag">&lt;/<span class="hljs-name">PackageProjectUrl</span>&gt;</span>
        <span class="hljs-comment">&lt;!--application versioning--&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AssemblyVersion</span>&gt;</span>1.1.0<span class="hljs-tag">&lt;/<span class="hljs-name">AssemblyVersion</span>&gt;</span>
        <span class="hljs-comment">&lt;!--general settings--&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">RestorePackages</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">RestorePackages</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PlatformTarget</span>&gt;</span>x64<span class="hljs-tag">&lt;/<span class="hljs-name">PlatformTarget</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TargetFramework</span>&gt;</span>net6.0-windows<span class="hljs-tag">&lt;/<span class="hljs-name">TargetFramework</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">LangVersion</span>&gt;</span>latest<span class="hljs-tag">&lt;/<span class="hljs-name">LangVersion</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Deterministic</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">Deterministic</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AppendTargetFrameworkToOutputPath</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">AppendTargetFrameworkToOutputPath</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AppendRuntimeIdentifierToOutputPath</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">AppendRuntimeIdentifierToOutputPath</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- unit test / visible to .Test assembly --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AssemblyAttribute</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"System.Runtime.CompilerServices.InternalsVisibleTo"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">_Parameter1</span>&gt;</span>$(AssemblyName).Tests<span class="hljs-tag">&lt;/<span class="hljs-name">_Parameter1</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">AssemblyAttribute</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!--general debug and release settings--&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)' == 'Debug' "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">DefineConstants</span>&gt;</span>TRACE;DEBUG;<span class="hljs-tag">&lt;/<span class="hljs-name">DefineConstants</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)' == 'Release' "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">DebugType</span>&gt;</span>portable<span class="hljs-tag">&lt;/<span class="hljs-name">DebugType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">OutputType</span>&gt;</span>Exe<span class="hljs-tag">&lt;/<span class="hljs-name">OutputType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!--
    dynamic project related 
    --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Project</span>&gt;</span>
</code></pre>
<h2 id="heading-conditions-configuration-build-configurations">Conditions, Configuration == build configurations</h2>
<p>Settings related to the configuration, platform or other conditions are next.</p>
<p>Do we really require different AnyCpu/x86/x64 conditions? Very rare required but mostly taking much space and causing big confusions (the platform target was already set in the first section.</p>
<p>If not, we can simply remove the platform condition by transferring:</p>
<p><code>&lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "&gt; .. &lt;/PropertyGroup&gt; &lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "&gt; ... &lt;/PropertyGroup&gt; &lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "&gt; .. &lt;/PropertyGroup&gt; &lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "&gt; ... &lt;/PropertyGroup&gt;</code> to: ```</p>
<p>true TRACE;DEBUG; portable ```</p>
<h2 id="heading-empty-project-folders">Empty project folders</h2>
<p>By using the upgrade-assistant, all empty folders without source files are integrated: <code>&lt;ItemGroup&gt; &lt;Folder Include="NyxMsSql\" /&gt; &lt;/ItemGroup&gt;</code> As it is just an empty folder, we delete the folder by using Solution Explorer. By handling it this way, the section is also automatically removed.</p>
<h2 id="heading-assemblyproject-references-and-nuget-packages">Assembly/project references and NuGet packages</h2>
<p>And finally, the nodes for the project/assembly references and the NuGet packages. I personally keep the project, then the assembly references and finally the NuGet packages, because NuGet packages are handled automatically.</p>
<h3 id="heading-summary">Summary</h3>
<p>With the latest upgrade-assistant it is, not anymore, such a big mess. However, the same structure of the project files is coming in very handy if working with dozens of projects.</p>
<p>One project file is done, two to go! : )</p>
<h3 id="heading-example-formatted-file">Example formatted file</h3>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">"Microsoft.NET.Sdk"</span>&gt;</span>
    <span class="hljs-comment">&lt;!--
    General settings, mostly the same for all projects
    --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
        <span class="hljs-comment">&lt;!--copyright --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Company</span>&gt;</span>Dominik Schischma<span class="hljs-tag">&lt;/<span class="hljs-name">Company</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Copyright</span>&gt;</span>Copyright © 2022<span class="hljs-tag">&lt;/<span class="hljs-name">Copyright</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PackageLicenseUrl</span>&gt;</span>www.sigterm.eu<span class="hljs-tag">&lt;/<span class="hljs-name">PackageLicenseUrl</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PackageProjectUrl</span>&gt;</span>www.sigterm.eu<span class="hljs-tag">&lt;/<span class="hljs-name">PackageProjectUrl</span>&gt;</span>
        <span class="hljs-comment">&lt;!--application versioning--&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AssemblyVersion</span>&gt;</span>0.0.1<span class="hljs-tag">&lt;/<span class="hljs-name">AssemblyVersion</span>&gt;</span>
        <span class="hljs-comment">&lt;!--general settings--&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">RestorePackages</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">RestorePackages</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PlatformTarget</span>&gt;</span>AnyCPU<span class="hljs-tag">&lt;/<span class="hljs-name">PlatformTarget</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TargetFramework</span>&gt;</span>net6.0-windows<span class="hljs-tag">&lt;/<span class="hljs-name">TargetFramework</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">LangVersion</span>&gt;</span>latest<span class="hljs-tag">&lt;/<span class="hljs-name">LangVersion</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Deterministic</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">Deterministic</span>&gt;</span>
        <span class="hljs-comment">&lt;!--do not create sub directories like 'net-6.0' --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AppendTargetFrameworkToOutputPath</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">AppendTargetFrameworkToOutputPath</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">AppendRuntimeIdentifierToOutputPath</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">AppendRuntimeIdentifierToOutputPath</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- build configuration --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)' == 'Debug' "</span>&gt;</span>
        <span class="hljs-comment">&lt;!--only use in debug!--&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">DefineConstants</span>&gt;</span>TRACE;DEBUG;<span class="hljs-tag">&lt;/<span class="hljs-name">DefineConstants</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)' == 'Release' "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">DebugType</span>&gt;</span>portable<span class="hljs-tag">&lt;/<span class="hljs-name">DebugType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- unit test / internals visible to .Tests assembly --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AssemblyAttribute</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"System.Runtime.CompilerServices.InternalsVisibleTo"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">_Parameter1</span>&gt;</span>$(AssemblyName).Tests<span class="hljs-tag">&lt;/<span class="hljs-name">_Parameter1</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">AssemblyAttribute</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!--
    nyxsql
    --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">OutputType</span>&gt;</span>WinExe<span class="hljs-tag">&lt;/<span class="hljs-name">OutputType</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">AssemblyName</span>&gt;</span>NyxSql<span class="hljs-tag">&lt;/<span class="hljs-name">AssemblyName</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">RootNamespace</span>&gt;</span>NyxSql<span class="hljs-tag">&lt;/<span class="hljs-name">RootNamespace</span>&gt;</span>
        <span class="hljs-comment">&lt;!--&lt;StartupObject&gt;Nyx.Program&lt;/StartupObject&gt;--&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ApplicationIcon</span>&gt;</span>Resources\Nyx.ico<span class="hljs-tag">&lt;/<span class="hljs-name">ApplicationIcon</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- still windows forms --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">UseWindowsForms</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">UseWindowsForms</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ImportWindowsDesktopTargets</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">ImportWindowsDesktopTargets</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!--non-classes &amp; usercontrols--&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\AutoCompletition\AcListBox.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>Component<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\PreviewTab.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\ProcedureTab.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Tools\Connection\ConnectionInput.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\SqlRichTextBox.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>Component<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\SqlTab.AutoCompletition.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>SqlTab.cs<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\TableTab.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\TriggerTab.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\ViewTab.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\SqlTab.cs"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!--project references--&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ProjectReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"..\NyxSettings\NyxSettings\NyxSettings.csproj"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!--assembly references--&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Assemblies\Mono.Security.dll"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>PreserveNewest<span class="hljs-tag">&lt;/<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Assemblies\MySql.Data.dll"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>PreserveNewest<span class="hljs-tag">&lt;/<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Assemblies\Npgsql.dll"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>PreserveNewest<span class="hljs-tag">&lt;/<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-comment">&lt;!--nuget--&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"odp.net.managed"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"121.1.2"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"System.Configuration.ConfigurationManager"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"5.0.0"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"0.4.346201"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">PrivateAssets</span>&gt;</span>all<span class="hljs-tag">&lt;/<span class="hljs-name">PrivateAssets</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">PackageReference</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Reference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MySql.Data, Version=5.0.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Private</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">Private</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Reference</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Reference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Npgsql, Version=0.99.3.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7, processorArchitecture=MSIL"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SpecificVersion</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">SpecificVersion</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">HintPath</span>&gt;</span>assemblies\Npgsql.dll<span class="hljs-tag">&lt;/<span class="hljs-name">HintPath</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Private</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">Private</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Reference</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Project</span>&gt;</span>
</code></pre>
<h3 id="heading-example-file-after-the-upgrade">Example file after the upgrade</h3>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">"Microsoft.NET.Sdk"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">TargetFramework</span>&gt;</span>net6.0-windows<span class="hljs-tag">&lt;/<span class="hljs-name">TargetFramework</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">OutputType</span>&gt;</span>WinExe<span class="hljs-tag">&lt;/<span class="hljs-name">OutputType</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">AssemblyName</span>&gt;</span>NyxSql<span class="hljs-tag">&lt;/<span class="hljs-name">AssemblyName</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">StartupObject</span>&gt;</span>Nyx.Program<span class="hljs-tag">&lt;/<span class="hljs-name">StartupObject</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ApplicationIcon</span>&gt;</span>Resources\Nyx.ico<span class="hljs-tag">&lt;/<span class="hljs-name">ApplicationIcon</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">SignAssembly</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">SignAssembly</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">AssemblyOriginatorKeyFile</span>&gt;</span>NyxKey.snk<span class="hljs-tag">&lt;/<span class="hljs-name">AssemblyOriginatorKeyFile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">TargetZone</span>&gt;</span>LocalIntranet<span class="hljs-tag">&lt;/<span class="hljs-name">TargetZone</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">GenerateManifests</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">GenerateManifests</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">SignManifests</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">SignManifests</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ManifestCertificateThumbprint</span>&gt;</span>37D2B3D67A093A04C499A9FE8A89B1EA7E3532D7<span class="hljs-tag">&lt;/<span class="hljs-name">ManifestCertificateThumbprint</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ApplicationRevision</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">ApplicationRevision</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">GenerateAssemblyInfo</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">GenerateAssemblyInfo</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">UseWindowsForms</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">UseWindowsForms</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ImportWindowsDesktopTargets</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">ImportWindowsDesktopTargets</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">UseVSHostingProcess</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">UseVSHostingProcess</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>On<span class="hljs-tag">&lt;/<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">DocumentationFile</span>&gt;</span>bin\Release\NyxSql.XML<span class="hljs-tag">&lt;/<span class="hljs-name">DocumentationFile</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">DebugType</span>&gt;</span>none<span class="hljs-tag">&lt;/<span class="hljs-name">DebugType</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">UseVSHostingProcess</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">UseVSHostingProcess</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>On<span class="hljs-tag">&lt;/<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">DocumentationFile</span>&gt;</span>bin\Release\NyxSql.XML<span class="hljs-tag">&lt;/<span class="hljs-name">DocumentationFile</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)|$(Platform)' == 'Debug|x86' "</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">OutputPath</span>&gt;</span>bin\x86\Debug\<span class="hljs-tag">&lt;/<span class="hljs-name">OutputPath</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">DocumentationFile</span>&gt;</span>bin\Release\NyxSql.XML<span class="hljs-tag">&lt;/<span class="hljs-name">DocumentationFile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">UseVSHostingProcess</span>&gt;</span>false<span class="hljs-tag">&lt;/<span class="hljs-name">UseVSHostingProcess</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>On<span class="hljs-tag">&lt;/<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span> <span class="hljs-attr">Condition</span>=<span class="hljs-string">" '$(Configuration)|$(Platform)' == 'Release|x86' "</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">OutputPath</span>&gt;</span>bin\x86\Release\<span class="hljs-tag">&lt;/<span class="hljs-name">OutputPath</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">CheckForOverflowUnderflow</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">DocumentationFile</span>&gt;</span>bin\Release\NyxSql.XML<span class="hljs-tag">&lt;/<span class="hljs-name">DocumentationFile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">DebugType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">DebugType</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>On<span class="hljs-tag">&lt;/<span class="hljs-name">GenerateSerializationAssemblies</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Reference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MySql.Data, Version=5.0.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Private</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">Private</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Reference</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Reference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Npgsql, Version=0.99.3.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7, processorArchitecture=MSIL"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SpecificVersion</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">SpecificVersion</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">HintPath</span>&gt;</span>assemblies\Npgsql.dll<span class="hljs-tag">&lt;/<span class="hljs-name">HintPath</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Private</span>&gt;</span>False<span class="hljs-tag">&lt;/<span class="hljs-name">Private</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Reference</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\AutoCompletition\AcListBox.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>Component<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\PreviewTab.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\ProcedureTab.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Tools\Connection\ConnectionInput.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\SqlRichTextBox.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>Component<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\SqlTab.AutoCompletition.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>SqlTab.cs<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\TableTab.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\TriggerTab.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\ViewTab.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"NyxControls\SqlTab.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SubType</span>&gt;</span>UserControl<span class="hljs-tag">&lt;/<span class="hljs-name">SubType</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Assemblies\Mono.Security.dll"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>PreserveNewest<span class="hljs-tag">&lt;/<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Assemblies\MySql.Data.dll"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>PreserveNewest<span class="hljs-tag">&lt;/<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Update</span>=<span class="hljs-string">"Assemblies\Npgsql.dll"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>PreserveNewest<span class="hljs-tag">&lt;/<span class="hljs-name">CopyToOutputDirectory</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">BaseApplicationManifest</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Properties\app.manifest"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ProjectReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"..\NyxSettings\NyxSettings\NyxSettings.csproj"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Folder</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"NyxMsSql\"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"odp.net.managed"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"121.1.2"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"System.Configuration.ConfigurationManager"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"5.0.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"0.4.346201"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">PrivateAssets</span>&gt;</span>all<span class="hljs-tag">&lt;/<span class="hljs-name">PrivateAssets</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">PackageReference</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Project</span>&gt;</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[NyxSql - a journey from .Net Framework to .Net 6 - Part I]]></title><description><![CDATA[Intro
In this series, I will write about upgrading a project which was created on .Net Framework 2 to .Net Core. All steps will be included, as in pushing to a fresh github repository and every major step of the migration.
NyxSql?
At first, the name ...]]></description><link>https://blog.sigterm.eu/nyxsql-a-journey-from-net-framework-to-net-6-part-i</link><guid isPermaLink="true">https://blog.sigterm.eu/nyxsql-a-journey-from-net-framework-to-net-6-part-i</guid><category><![CDATA[C#]]></category><category><![CDATA[upgrade-assistant]]></category><category><![CDATA[framework upgrade]]></category><category><![CDATA[.net migration]]></category><category><![CDATA[nyxsql]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Fri, 16 Sep 2022 18:32:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/QoNI4StOPgU/upload/v1663352983174/CaxhVmNS5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-intro">Intro</h2>
<p>In this series, I will write about upgrading a project which was created on .Net Framework 2 to .Net Core. All steps will be included, as in pushing to a fresh github repository and every major step of the migration.</p>
<h3 id="heading-nyxsql">NyxSql?</h3>
<p>At first, the name was inspired by <a target="_blank" href="https://en.wikipedia.org/wiki/Nyx">Nyx</a>. I decided to write this program over a decade ago, due to the lag of universal sql editors / gui tools from windows to most common databases. It was intended to be a learning project using WinForms. As I mainly used it for Oracle database it was abandoned by me when <a target="_blank" href="https://www.oracle.com/database/sqldeveloper/">SqlDeveloper</a> was released.</p>
<h3 id="heading-restore-of-the-sources-and-upload-to-github">Restore of the sources and upload to github</h3>
<ul>
<li>Unzipped the old svn backup </li>
<li>Removed the .svn folder </li>
</ul>
<h3 id="heading-git-repository">Git repository</h3>
<p>Currently I created a private git repository at <a target="_blank" href="https://github.com/">GitHub</a>. Perhaps I will make it public at some time, but due to bad experiences with projects, which had been completely cloned and used without any credits, I am keeping it private right now.</p>
<h3 id="heading-first-loading-of-project-after-some-years">First loading of project after some years</h3>
<p>After git was pushed and all files in place, I opened the solution with Visual Studio. The very first question which came was the 'Target framework not supported', where the upgrade to 4.8 was confirmed. </p>
<p>Afterwards a whole batch build and installation of odp.net.managed nuget package. Then NyxSql started without any further complains! As happy as I was about the successful start, as ugly is the GUI.. but we will have another article about that.</p>
<h3 id="heading-upgrade-assistant">Upgrade assistant</h3>
<p>For upgrading from .Net Framework or .Net Core to .Net we can use the <a target="_blank" href="https://dotnet.microsoft.com/en-us/platform/upgrade-assistant">.net upgrade assistant</a> from Microsoft. I personally prefer to visit the <a target="_blank" href="https://github.com/dotnet/upgrade-assistant">github project page</a> directly.</p>
<p>Now we require a command prompt (cmd) or powershell for executing the following commands.</p>
<p>Installation:</p>
<pre><code>dotnet tool install <span class="hljs-operator">-</span>g <span class="hljs-operator">-</span><span class="hljs-operator">-</span>add<span class="hljs-operator">-</span>source https:<span class="hljs-comment">//api.nuget.org/v3/index.json --ignore-failed-sources upgrade-assistant</span>
</code></pre><p>or if it is already installed, the update:</p>
<pre><code>dotnet tool update <span class="hljs-operator">-</span>g <span class="hljs-operator">-</span><span class="hljs-operator">-</span>add<span class="hljs-operator">-</span>source https:<span class="hljs-comment">//api.nuget.org/v3/index.json --ignore-failed-sources upgrade-assistant</span>
</code></pre><h2 id="heading-the-upgrade-itself">The upgrade itself</h2>
<p>Open a powershell and change to the project directory, e.g.:
<code>sl d:\source\c#\NyxSql</code></p>
<p>Then we start the upgrade with:
<code>upgrade-assistant upgrade --skip-backup --non-interactive Nyx.sln</code></p>
<p>Where we use:</p>
<ul>
<li>skip-backup as we are using git and need no file backup</li>
<li>non-interactive as we do not want to press 'y' over and over again for each project</li>
</ul>
<h2 id="heading-warnings-errors">Warnings / errors</h2>
<p>After the upgrade is finished, you should analyze the output for warnings. When upgrading NyxSql we got for example following warnings:</p>
<pre><code>[20:18:16 WRN] Default font in Windows Forms has been changed from Microsoft Sans Serif to Seg Segoe UI, in order to <span class="hljs-keyword">change</span> the <span class="hljs-keyword">default</span> font <span class="hljs-keyword">use</span> the API - Application.SetDefaultFont(Font font). <span class="hljs-keyword">For</span> more details see here - https://devblogs.microsoft.com/<span class="hljs-keyword">dotnet</span>/whats-<span class="hljs-keyword">new</span>-<span class="hljs-keyword">in</span>-windows-forms-<span class="hljs-keyword">in</span>-net<span class="hljs-number">-6</span><span class="hljs-number">-0</span>-preview<span class="hljs-number">-5</span>/<span class="hljs-comment">#application-wide-default-font.</span>
[<span class="hljs-number">20</span>:<span class="hljs-number">18</span>:<span class="hljs-number">41</span> WRN] <span class="hljs-keyword">No</span> <span class="hljs-keyword">version</span> <span class="hljs-keyword">of</span> odp.net.managed <span class="hljs-keyword">found</span> that supports [<span class="hljs-string">"net6.0-windows"</span>]; leaving unchanged
[20:18:43 WRN] HighDpiMode needs to <span class="hljs-keyword">set</span> <span class="hljs-keyword">in</span> <span class="hljs-keyword">Main</span>() instead <span class="hljs-keyword">of</span> app.config <span class="hljs-keyword">or</span> app.manifest - Application.SetHighDpiMode(HighDpiMode.&lt;setting&gt;). It <span class="hljs-keyword">is</span> recommended <span class="hljs-keyword">to</span> <span class="hljs-keyword">use</span> SystemAware <span class="hljs-keyword">as</span> the HighDpiMode <span class="hljs-keyword">option</span> <span class="hljs-keyword">for</span> better results.
[<span class="hljs-number">20</span>:<span class="hljs-number">19</span>:<span class="hljs-number">02</span> WRN] <span class="hljs-keyword">Manual</span> updates needed <span class="hljs-keyword">to</span> address: UA0013_M@SourceFile(d:\<span class="hljs-keyword">source</span>\c<span class="hljs-comment">#\NyxSql\Nyx\Tools\UserSettingsManager\DisplayProperty.cs[1462..1470)): Windows Forms Deprecated controls : DataGrid needs to be replaced with DataGridView. For more details see - https://docs.microsoft.com/en-us/dotnet/core/compatibility/winforms#removed-controls</span>
</code></pre><p>Next to the solution Nyx it was also required to update NyxUpdate.sln in another step.</p>
<p>In the next article we will look at how to create plain project files and if we can run the project.</p>
]]></content:encoded></item><item><title><![CDATA[Oracle Database - data file / space handling]]></title><description><![CDATA[Intro
As I am already working a very long time (around 22 years) with oracle databases using file storage (no ASM, datafiles), a repetitive task always has been managing and extending the datafiles. This post is more a scratchpad of common queries I ...]]></description><link>https://blog.sigterm.eu/oracle-database-data-file-space-handling</link><guid isPermaLink="true">https://blog.sigterm.eu/oracle-database-data-file-space-handling</guid><category><![CDATA[Oracle]]></category><category><![CDATA[datafile]]></category><category><![CDATA[tablespace]]></category><category><![CDATA[tempfile]]></category><category><![CDATA[space usage]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Thu, 15 Sep 2022 18:42:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/AcW1ZwD-qC0/upload/v1663267375504/3eiYY_sCB.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-intro">Intro</h3>
<p>As I am already working a very long time (around 22 years) with oracle databases using file storage (no ASM, datafiles), a repetitive task always has been managing and extending the datafiles. This post is more a scratchpad of common queries I used to handle the file storage.
Please refer to the official oracle documentation if you are not yet used to file handling as this blog post is no replacement for the oracle documentation nor make me responsible if you made something stupid : )</p>
<p>The post will be extended step by step... </p>
<h3 id="heading-caution">CAUTION</h3>
<p>Before extending oracle files, always make sure to check the:</p>
<ul>
<li>free disk space in advance</li>
<li>naming of the file that it is 'in line' with the other data files</li>
</ul>
<p>Imho, best practice for file names is the following schematics: __.dbf 
Naturally, the extension is free of choice, dbf for DataBaseFile</p>
<h2 id="heading-tabelspace">Tabelspace</h2>
<p>A tablespace is a logical organization unit for one or more datafiles. The datafiles itself are holding the data, not the tablespace.</p>
<h3 id="heading-space-overview">Space overview</h3>
<pre><code>SELECT df.tablespace_name <span class="hljs-string">"TS"</span>,
       df.total_gb <span class="hljs-string">"GB total"</span>,
       used_gb <span class="hljs-string">"GB used"</span>,
       (df.total_gb <span class="hljs-operator">-</span> ds.used_gb) <span class="hljs-string">"GB free"</span>,
       ROUND(<span class="hljs-number">100</span> <span class="hljs-operator">*</span> ( (df.total_gb <span class="hljs-operator">-</span> ds.used_gb)<span class="hljs-operator">/</span> df.total_gb),<span class="hljs-number">2</span>) <span class="hljs-string">"% free"</span>
  FROM (SELECT tablespace_name, 
               ROUND(SUM(<span class="hljs-keyword">bytes</span>) <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>,<span class="hljs-number">2</span>) total_gb
          FROM dba_data_files
         GROUP BY tablespace_name) df,
       (SELECT ROUND(SUM(<span class="hljs-keyword">bytes</span>)<span class="hljs-operator">/</span>(<span class="hljs-number">1024</span><span class="hljs-operator">*</span><span class="hljs-number">1024</span><span class="hljs-operator">*</span><span class="hljs-number">1024</span>),<span class="hljs-number">2</span>) used_gb, 
               tablespace_name
          FROM dba_segments
         GROUP BY tablespace_name) ds
 WHERE df.tablespace_name <span class="hljs-operator">=</span> ds.tablespace_name;
</code></pre><p>Output is in GB - if you wish to use MB, just remove one 1024 in line 7 and 10.</p>
<h3 id="heading-add">Add</h3>
<p>Here we add a new tablespace 'NEWTS' with one datafile:</p>
<pre><code><span class="hljs-keyword">create</span> <span class="hljs-keyword">tablespace</span> NEWTS
   <span class="hljs-keyword">DATAFILE</span> <span class="hljs-string">'/opt/ora/data/EXA/NEWTS/EXA_NEWTS_01.dbf'</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">2</span>M;
</code></pre><p>Now with two:</p>
<pre><code><span class="hljs-keyword">create</span> <span class="hljs-keyword">tablespace</span> NEWTS
   <span class="hljs-keyword">DATAFILE</span> <span class="hljs-string">'/opt/ora/data/EXA/NEWTS/EXA_NEWTS_01.dbf'</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">2</span>M,
                    <span class="hljs-string">'/opt/ora/data/EXA/NEWTS/EXA_NEWTS_02.dbf'</span> <span class="hljs-keyword">SIZE</span> <span class="hljs-number">2</span>M;
</code></pre><h3 id="heading-drop">Drop</h3>
<p>Really? : )</p>
<pre><code><span class="hljs-keyword">drop</span> <span class="hljs-keyword">tablespace</span> NEWTS;
</code></pre><p>If you want to drop the tablespace with ALL content:</p>
<pre><code><span class="hljs-keyword">drop</span> <span class="hljs-keyword">tablespace</span> NEWTS <span class="hljs-keyword">including</span> <span class="hljs-keyword">contents</span>;
</code></pre><h2 id="heading-datafiles">Datafiles</h2>
<h3 id="heading-space-overview">Space overview</h3>
<pre><code>SELECT df.NAME <span class="hljs-keyword">as</span> file_name, 
       round(df.bytes <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>,<span class="hljs-number">2</span>) <span class="hljs-string">"GB total"</span>,
       round(((df.bytes <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>) <span class="hljs-operator">-</span> NVL (SUM (dfs.bytes) <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>, <span class="hljs-number">0</span>)),<span class="hljs-number">2</span>) <span class="hljs-string">"GB used"</span>,
       round(NVL (SUM (dfs.bytes) <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>, <span class="hljs-number">0</span>),<span class="hljs-number">2</span>) <span class="hljs-string">"GB free"</span>
  FROM v$datafile df, dba_free_space dfs
 WHERE df.file# <span class="hljs-operator">=</span> dfs.file_id(<span class="hljs-operator">+</span>)
 GROUP BY dfs.file_id, df.NAME, df.file#, df.bytes
 ORDER BY file_name;
</code></pre><h3 id="heading-add">Add</h3>
<p>Tablespace name in this example is "NEWTS"</p>
<pre><code><span class="hljs-keyword">alter</span> <span class="hljs-keyword">tablespace</span> NEWTS <span class="hljs-keyword">add</span> <span class="hljs-keyword">datafile</span> <span class="hljs-string">'/opt/ora/data/EXA/NEWTS/EXA_NEWTS_03.dbf'</span> <span class="hljs-keyword">size</span> <span class="hljs-number">32</span>M;
</code></pre><h3 id="heading-resize">Resize</h3>
<pre><code><span class="hljs-keyword">alter</span> <span class="hljs-keyword">database</span> <span class="hljs-keyword">datafile</span> <span class="hljs-string">'/opt/ora/data/EXA/NEWTS/EXA_NEWTS_03.dbf'</span> <span class="hljs-keyword">resize</span> <span class="hljs-number">64</span>M;
</code></pre><h2 id="heading-tempfiles">Tempfiles</h2>
<h3 id="heading-space-overview">Space overview</h3>
<pre><code>SELECT tf.NAME file_name, 
       round(tf.bytes <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>,<span class="hljs-number">2</span>) <span class="hljs-string">"GB total"</span>,
       round(((tf.bytes <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>) <span class="hljs-operator">-</span> NVL (SUM (dfs.bytes) <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>, <span class="hljs-number">0</span>)),<span class="hljs-number">2</span>) <span class="hljs-string">"GB used"</span>,
       round(NVL (SUM (dfs.bytes) <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span> <span class="hljs-operator">/</span> <span class="hljs-number">1024</span>, <span class="hljs-number">0</span>),<span class="hljs-number">2</span>) <span class="hljs-string">"GB free"</span>
  FROM v$tempfile tf, dba_free_space dfs
 WHERE tf.file# <span class="hljs-operator">=</span> dfs.file_id(<span class="hljs-operator">+</span>)
 GROUP BY dfs.file_id, tf.NAME, tf.file#, tf.bytes
 ORDER BY file_name;
</code></pre><h3 id="heading-add">Add</h3>
<p>Temporary tablespace name in this example is "temp_data"</p>
<pre><code><span class="hljs-keyword">alter</span> <span class="hljs-keyword">tablespace</span> temp_data <span class="hljs-keyword">add</span> tempfile <span class="hljs-string">'/opt/ora/temp/EXA/EXA_temp_03.dbf'</span> <span class="hljs-keyword">size</span> <span class="hljs-number">32</span>M;
</code></pre><h3 id="heading-resize">Resize</h3>
<pre><code><span class="hljs-keyword">alter</span> <span class="hljs-keyword">database</span> tempfile <span class="hljs-string">'/opt/ora/temp/EXA/EXA_temp_03.dbf'</span> <span class="hljs-keyword">resize</span> <span class="hljs-number">64</span>M;
</code></pre>]]></content:encoded></item><item><title><![CDATA[.Net 5/6... application versioning howto]]></title><description><![CDATA[Until we switched to .net 6 from the .net framework we used a major.minor (m.xxx) versioning together with the compile/build time as build number. 
Verifying the build number together with the version when has proven itself when it is coming to many ...]]></description><link>https://blog.sigterm.eu/net-56-application-versioning-howto</link><guid isPermaLink="true">https://blog.sigterm.eu/net-56-application-versioning-howto</guid><category><![CDATA[C#]]></category><category><![CDATA[build]]></category><category><![CDATA[version]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Sun, 24 Jul 2022 03:18:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/g4WinrGsMl0/upload/v1658632637262/XQUYha1pC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Until we switched to .net 6 from the .net framework we used a major.minor (m.xxx) versioning together with the compile/build time as build number. </p>
<p>Verifying the build number together with the version when has proven itself when it is coming to many builds in short time (to deploy multiple changes to multiple customers).</p>
<p>In .net this can be handled by the project file directly using these 2 properties:</p>
<pre><code><span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>application versioning<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>AssemblyVersion<span class="hljs-operator">&gt;</span><span class="hljs-number">6.6</span><span class="hljs-number">.0</span><span class="hljs-number">.3</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>AssemblyVersion<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>SourceRevisionId<span class="hljs-operator">&gt;</span>build$([System.DateTime]::UtcNow.ToString(<span class="hljs-string">"yyyyMMddHHmmss"</span>))<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>SourceRevisionId<span class="hljs-operator">&gt;</span>
</code></pre><p>Please note, not to use the old AssemblyInfo.cs as this will result in a conflict.</p>
<p>After this change, the correct version and 'revision' is visible in the properties of the executable. But how to retrieve it? 
Really, in the first minutes I was very confused... However here is the solution:</p>
<pre><code><span class="hljs-keyword">public</span> static (<span class="hljs-keyword">string</span> AppName, <span class="hljs-keyword">string</span> Version, <span class="hljs-keyword">string</span> Build) GetCSharpVersion()
{
    <span class="hljs-keyword">var</span> entryAssembly <span class="hljs-operator">=</span> Assembly.GetEntryAssembly();
    <span class="hljs-keyword">if</span> (entryAssembly <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null)
        <span class="hljs-keyword">return</span> (<span class="hljs-string">"itxClLogon"</span>, <span class="hljs-string">"0.00"</span>, <span class="hljs-string">"0"</span>);

    <span class="hljs-keyword">string</span> appName <span class="hljs-operator">=</span> entryAssembly.GetName().Name;
    <span class="hljs-keyword">var</span> appVersion <span class="hljs-operator">=</span> entryAssembly.GetName().Version;

    DateTime buildDate <span class="hljs-operator">=</span> DateTime.MinValue;

    const <span class="hljs-keyword">string</span> buildVersionMetadataPrefix <span class="hljs-operator">=</span> <span class="hljs-string">"+build"</span>;
    <span class="hljs-keyword">var</span> attribute <span class="hljs-operator">=</span> entryAssembly.GetCustomAttribute&lt;AssemblyInformationalVersionAttribute<span class="hljs-operator">&gt;</span>();
    <span class="hljs-keyword">if</span> (attribute?.InformationalVersion <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) 
        <span class="hljs-keyword">return</span> (appName, $<span class="hljs-string">"{appVersion}"</span>, $<span class="hljs-string">"{buildDate:yyyyMMdd.HHmm}"</span>);
    <span class="hljs-keyword">var</span> value <span class="hljs-operator">=</span> attribute.InformationalVersion;
    <span class="hljs-keyword">var</span> index <span class="hljs-operator">=</span> value.IndexOf(buildVersionMetadataPrefix, StringComparison.Ordinal);
    <span class="hljs-keyword">if</span> (index <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>)
    {
        value <span class="hljs-operator">=</span> value.Substring(index <span class="hljs-operator">+</span> buildVersionMetadataPrefix.Length);
        DateTime.TryParseExact(value, <span class="hljs-string">"yyyyMMddHHmmss"</span>, CultureInfo.InvariantCulture, DateTimeStyles.None, out buildDate);
    }

    <span class="hljs-keyword">return</span> (appName, $<span class="hljs-string">"{appVersion}"</span>, $<span class="hljs-string">"{buildDate:yyyyMMdd.HHmm}"</span>);
}
</code></pre><p>Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[c# Visual Studio turn off auto formatting for code area]]></title><description><![CDATA[Sometimes you do not want to have auto formatting enabled for specific code areas. Mostly I am using that for short switch statements, for a better code readability.
Specific code areas can be excluded by using the formatter directive:
switch (arg.To...]]></description><link>https://blog.sigterm.eu/c-visual-studio-turn-off-auto-formatting-for-code-area</link><guid isPermaLink="true">https://blog.sigterm.eu/c-visual-studio-turn-off-auto-formatting-for-code-area</guid><category><![CDATA[C#]]></category><category><![CDATA[visual studio]]></category><category><![CDATA[format]]></category><category><![CDATA[formatting]]></category><category><![CDATA[code format]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Mon, 27 Jun 2022 11:17:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/59yRYIHWtzY/upload/v1656304013751/ASuznCOiD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sometimes you do not want to have auto formatting enabled for specific code areas. Mostly I am using that for short switch statements, for a better code readability.</p>
<p>Specific code areas can be excluded by using the formatter directive:</p>
<pre><code>switch (arg.ToLower())
{
  <span class="hljs-comment">// @formatter:off</span>
  case <span class="hljs-string">"create"</span>: action <span class="hljs-operator">=</span> CliAction.Create; <span class="hljs-keyword">break</span>;
  case <span class="hljs-string">"list"</span>: action <span class="hljs-operator">=</span> CliAction.List; <span class="hljs-keyword">break</span>;
  <span class="hljs-comment">// @formatter:on</span>
}
</code></pre>]]></content:encoded></item><item><title><![CDATA[Sophos & OCI IPSec site2site parameters]]></title><description><![CDATA[About connecting our on-premises environment using an IPSec Site-to-Site (s2s) connection between our on premises Sophos (SFOS 19.x) and Oracle Cloud Infrastructure (OCI) using IKEv2.
As always, when I connect 2 foreign device vendors, testing differ...]]></description><link>https://blog.sigterm.eu/sophos-and-oci-ipsec-site2site-parameters</link><guid isPermaLink="true">https://blog.sigterm.eu/sophos-and-oci-ipsec-site2site-parameters</guid><category><![CDATA[OCI]]></category><category><![CDATA[ipsec]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[site-to-site]]></category><category><![CDATA[s2s]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Thu, 16 Jun 2022 05:06:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/8yy05SPf3rQ/upload/v1655355903721/ipAyb6Onp.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>About connecting our on-premises environment using an IPSec Site-to-Site (s2s) connection between our on premises Sophos (SFOS 19.x) and Oracle Cloud Infrastructure (OCI) using IKEv2.</p>
<p>As always, when I connect 2 foreign device vendors, testing different parameters and algorithms for the connection (...but they nearly all use <a target="_blank" href="https://www.strongswan.org/">strongswan</a>...). After some time, the connection was established for phase 1 and phase 2 (note, that the IPSec identifiers are the corresponding IP addresses, if 'IP Address' is selected in OCI).</p>
<p>Sadly, after the initial connection was established, the connection always dropped when the IPSEC Phase2 rekey timeout was reached.</p>
<p>Took some time to find correct phase 2 parameters, so I wanted to share the final parameters which came out to work stable:</p>
<table>
<thead>
</thead><td>Phase</td>
<td>Parameter</td>
<td>OCI</td>
<td>Sophos</td>

<tr>
<td></td>
<td>Dead Peer Detection</td>
<td>Respond only</td>
<td>Turned off</td>
</tr>
<tr>
<td>1</td>
<td>Custom Encryption Algorithm</td>
<td>AES_256_CBC</td>
<td>AES256</td>
</tr>
<tr>
<td></td>
<td>Custom Authentication Algorithm</td>
<td>SHA2_384</td>
<td>SHA2 384</td>
</tr>
<tr>
<td></td>
<td>Custom Diffie-Hellman Group</td>
<td>GROUP20</td>
<td>20 (ecp384)</td>
</tr>
<tr>
<td></td>
<td>IKE session key lifetime in seconds</td>
<td>28800</td>
<td>28800</td>
</tr>

<tr>
<td>2</td>
<td>Custom Encryption Algorithm</td>
<td>AES_256_GCM</td>
<td>AES256GCM16</td>
</tr>
<tr>
<td></td>
<td>Custom Authentication Algorithm</td>
<td>None</td>
<td>None</td>
</tr>
<tr>
<td></td>
<td>IKE session key lifetime in seconds</td>
<td>3600</td>
<td>3600</td>
</tr>
<tr>
<td></td>
<td>Perfect Forwarding Security</td>
<td><strong>Enabled</strong> GROUP5</td>
<td>GROUP5</td>
</tr>
</table>

<p>Another great reference can be found <a target="_blank" href="[https://www.ateam-oracle.com/post/oracle-cloud-vpn-connect-troubleshooting]">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[.Net Core and above (5,6,...) windows service / linux systemd]]></title><description><![CDATA[Intro
While windows services had their own implementation classes in the .Net Framework, when migrating to .Net (Core) we noticed that we had to re-implement the whole service control.
Our requirements are, imho, basic requirements for a background w...]]></description><link>https://blog.sigterm.eu/net-core-and-above-56-windows-service-linux-systemd</link><guid isPermaLink="true">https://blog.sigterm.eu/net-core-and-above-56-windows-service-linux-systemd</guid><category><![CDATA[C#]]></category><category><![CDATA[windows service]]></category><category><![CDATA[linux systemd]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Sat, 11 Jun 2022 05:19:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/zGuBURGGmdY/upload/v1655011781876/A3PCJzhYM.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-intro">Intro</h3>
<p>While windows services had their own implementation classes in the .Net Framework, when migrating to .Net (Core) we noticed that we had to re-implement the whole service control.</p>
<p>Our requirements are, imho, basic requirements for a background windows service:</p>
<ul>
<li>Is getting notified when the service controller is stopping the service</li>
<li>Can stop itself from within on a fatal error</li>
<li>Will run below windows service and linux systemd</li>
</ul>
<h3 id="heading-required-nuget">Required nuget</h3>
<p>For integration we require the NuGet package <a target="_blank" href="https://www.nuget.org/packages/Microsoft.Extensions.Hosting.WindowsServices/6.0.0?_src=template">Microsoft.Extensions.Hosting.WindowsServices</a>. There is also one for the systemd part of Linux (Microsoft.Extensions.Hosting.Systemd), however I will cover that later.</p>
<h3 id="heading-the-main-entry-point-for-the-service">The main entry point for the service</h3>
<p>We use the Program.cs for starting up the service. Normally, before I start the service itself, I verify the settings and so on. If we just return from the main method, the service will not start using the windows service controller and throw an error 'service could not be started'.</p>
<pre><code>static async Task Main(<span class="hljs-keyword">string</span>[] args)
{
    <span class="hljs-comment">// load settings / verify environment....</span>

    <span class="hljs-comment">// start the service </span>
    <span class="hljs-keyword">using</span> <span class="hljs-title">IHost</span> <span class="hljs-title">host</span> <span class="hljs-operator">=</span> <span class="hljs-title">Host</span>.<span class="hljs-title">CreateDefaultBuilder</span>(<span class="hljs-title">args</span>)
        .<span class="hljs-title">UseWindowsService</span>(<span class="hljs-title">options</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
            {
                <span class="hljs-title">options</span>.<span class="hljs-title">ServiceName</span> <span class="hljs-operator">=</span> "<span class="hljs-title">MyServiceName</span>";
            })
            .UseSystemd()
            .ConfigureServices(services <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
            {
                services.AddHostedService&lt;CustomService <span class="hljs-operator">&gt;</span>();
             })
             .Build();
    await host.RunAsync();
}
</code></pre><h3 id="heading-background-service-class">Background service class</h3>
<p>We start, by deriving our CustomService.cs from BackgroundService where we must override the ExecuteAsync method:</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomService</span> :</span> BackgroundService
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> Task <span class="hljs-title">ExecuteAsync</span><span class="hljs-params">(CancellationToken stoppingToken)</span>
    </span>{
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> NotImplementedException();
    }
}
</code></pre><p>The stoppingToken is cancelled when the service is stopped by the service controller. It is brought to use by the dependency injection, what we can also use to get a reference to the <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostapplicationlifetime?view=dotnet-plat-ext-6.0">IHostApplicationLifetime</a> from the constructor, which we save us for later in the class itself AND directly register to a delegate which is getting executed when the application is stopping:</p>
<pre><code>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IHostApplicationLifetime _appLifeTime;

    <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;summary&gt;</span> constructor <span class="hljs-doctag">&lt;/summary&gt;</span></span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CustomService</span>(<span class="hljs-params">IHostApplicationLifetime appLifeTime</span>)</span>
    {
        _appLifeTime = appLifeTime;
        _appLifeTime.ApplicationStopping.Register(AppStopping);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">AppStopping</span>(<span class="hljs-params"></span>)</span>
    {

    }
</code></pre><p>By the delegate registration we do not require to loop, checking the stoppingToken, for the current state.</p>
<h3 id="heading-stopping-ourselves">Stopping ourselves</h3>
<p>By using the IHostApplicationLifetime we can stop ourselves pretty simple:</p>
<pre><code>_appLifeTime.StopApplication();
</code></pre><p>Be aware, that the delegate ApplicationStopping is also executed!</p>
<h3 id="heading-installation-on-windows">Installation on windows</h3>
<p>The previous windows service installation was based on a 'service installer' which was executed after starting the 'installutil.exe' from the .net framework folder</p>
<p>This is not anymore valid, so we use the <a target="_blank" href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-service?view=powershell-7.2">New-Service cmdlet</a>, which also has got much more options than the previous method using the 'service installer'. </p>
<p>To use the cmdlet, take a look <a target="_blank" href="https://docs.microsoft.com/en-us/powershell/scripting/developer/hosting/adding-and-invoking-commands?view=powershell-7.2">here</a>. I even prefer this method about invoke the windows apis directly.</p>
<h3 id="heading-installation-on-linux">Installation on linux</h3>
<p>On Linux we require a systemd services file. Here we will create a system service called 'sample-dotnet':  </p>
<pre><code>vi <span class="hljs-operator">/</span>etc<span class="hljs-operator">/</span>systemd<span class="hljs-operator">/</span>system<span class="hljs-operator">/</span>sample<span class="hljs-operator">-</span>dotnet.service
</code></pre><p>Content:</p>
<pre><code><span class="hljs-comment"># reload: systemctl deamon-reload</span>
<span class="hljs-comment"># enable: systemctl enable itxprdsrv.service</span>

<span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=sample dotnet service

<span class="hljs-section">[Service]</span>
<span class="hljs-attr">User</span>=opc
<span class="hljs-attr">Type</span>=simple
<span class="hljs-attr">ExecStart</span>=/opt/sample-dotnet
<span class="hljs-attr">TimeoutStopSec</span>=<span class="hljs-number">2</span>

<span class="hljs-section">[Install]</span>
<span class="hljs-attr">WantedBy</span>=multi-user.target
</code></pre><p>Afterwards, reload and enable systemd:</p>
<pre><code>systemctl deamon<span class="hljs-operator">-</span>reload
systemctl enable sample<span class="hljs-operator">-</span>dotnet.service
</code></pre><p>Naturally you have to set the executable the execute permission:</p>
<pre><code>chmod <span class="hljs-operator">+</span>x <span class="hljs-operator">/</span>opt<span class="hljs-operator">/</span>sample<span class="hljs-operator">-</span>dotnet
</code></pre><p>If you have SELinux enabled, this will block it. In development environments we can work around by:</p>
<pre><code>semanage fcontext <span class="hljs-operator">-</span>a <span class="hljs-operator">-</span>t bin_t <span class="hljs-string">'sample-dotnet'</span>
</code></pre>]]></content:encoded></item><item><title><![CDATA[Controlling an AS/400 or System i with c#]]></title><description><![CDATA[Introduction
Some time ago we had to develop and deploy a new system side application for our customers. As our customer base is using mainly Windows and System i, and our whole new system configurations have been developed in c# we had to decide whi...]]></description><link>https://blog.sigterm.eu/controlling-an-as400-or-system-i-with-c</link><guid isPermaLink="true">https://blog.sigterm.eu/controlling-an-as400-or-system-i-with-c</guid><category><![CDATA[C#]]></category><category><![CDATA[SystemI]]></category><category><![CDATA[as400]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Wed, 08 Jun 2022 03:29:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/0mXw-dvuLok/upload/v1654658919064/RaGvpI3KG.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Some time ago we had to develop and deploy a new system side application for our customers. As our customer base is using mainly Windows and System i, and our whole new system configurations have been developed in c# we had to decide which way we go. 
Either rewrite the current codebase in c++ and port it to System i or find another solution. As c++ is very specific on the System i, it would have been an own development on its own.</p>
<p>After some digging in the internet I came across some articles (sadly I haven't saved them, so I cannot reference these) which described the execution of scripts by using sql (strsql) on the System i. </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>I installed the IBM i Access client solution on my dev workstation, including the ODBC-Drivers for DB2 and started up Visual Studio. As a side note: at this time there was no native .net DB2 driver and later on I never got it really running - however as we want to control the System i and not transfer insert/update many data in the database, I did not care about using ODBC.</p>
<p>The whole integration ended up in using:</p>
<ul>
<li>ODBC to access the database and execute commandos (Access to QSYS.QCMDEXC required</li>
<li>The IFS (integrated file system) for transferring files by SMB/CIFS </li>
</ul>
<p>A specific connection string should be used, to set the required library list:</p>
<pre><code>Driver<span class="hljs-operator">=</span>{Client Access ODbC Driver (<span class="hljs-number">32</span><span class="hljs-operator">-</span>bit)};System<span class="hljs-operator">=</span>i5system;Uid<span class="hljs-operator">=</span>user;Pwd<span class="hljs-operator">=</span>password;DefaultLibraries<span class="hljs-operator">=</span>ITLIB1,ITLIB2
</code></pre><h3 id="heading-executing-cl-procedures">Executing cl procedures</h3>
<p>By executing a normal 'non query' and <a target="_blank" href="https://www.ibm.com/docs/en/i/7.1?topic=ssw_ibm_i_71/apis/qcmdexc.htm">QSYS.QCMDEXC</a> we can execute any command. Here we will execute a CL procedure in ITLIB2 which is called TESTCN. The CL procedure which we call will receive 2 parameters and the 'native' call on the System i is stored in the variable clCmd:</p>
<pre><code>string clCmd = "<span class="hljs-keyword">CALL</span> PGM(ITLIB2/TESTCN) PARM(<span class="hljs-string">'1stParam'</span> <span class="hljs-string">'2condParam'</span>)<span class="hljs-string">";</span>
</code></pre><p>The call itself, please note that we need to escape the single quotes ' when using them in the sql query. Furthermore, QCMDEXC does require the length of the command string in 15,5 packed format.</p>
<pre><code> <span class="hljs-keyword">string</span> pgmParm <span class="hljs-operator">=</span> $<span class="hljs-string">"CALL QSYS.QCMDEXC('{cmdtext.Replace("</span><span class="hljs-string">'", "'</span><span class="hljs-string">'")}'</span>, {clCmd.Length.ToString(<span class="hljs-string">"0000000000.00000"</span>).Replace(<span class="hljs-string">','</span>, <span class="hljs-string">'.'</span>)})<span class="hljs-string">";</span>
</code></pre><h3 id="heading-error-handling">Error handling</h3>
<p>An error at calling will throw an exception (OdbcException) which can then be examined for the exact error code.</p>
<h3 id="heading-spool-files">Spool files</h3>
<p>For reading spool files with SQL, <a target="_blank" href="https://www.ibm.com/docs/en/i/7.4?topic=systools-using">SYSTOOLS</a> with <a target="_blank" href="https://www.ibm.com/docs/en/i/7.4?topic=services-spooled-file-data-table-function">SPOOLED_FILE_DATA</a> is available. </p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Naturally, a native port would have been much better implementation BUT by creating some CL procedures and building up an architecture where the platform calls are handled by specific procedures/functions we got a fluent integration which can run from any windows operating system.</p>
]]></content:encoded></item><item><title><![CDATA[Codepages, character set, encoding... uh?]]></title><description><![CDATA[One of the most asked questions while training is about codepages or character sets. Ever met some strange characters in e-mails, documents or the internet? Like '???? ?? ???' or '¿¿¿¿' and others. 
History bit/byte
Let us start from the beginning. T...]]></description><link>https://blog.sigterm.eu/codepages-character-set-encoding-uh</link><guid isPermaLink="true">https://blog.sigterm.eu/codepages-character-set-encoding-uh</guid><category><![CDATA[C#]]></category><category><![CDATA[encoding]]></category><category><![CDATA[character sets]]></category><category><![CDATA[codepages]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Sun, 05 Jun 2022 03:49:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654270420736/XB02nQDq1.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the most asked questions while training is about codepages or character sets. Ever met some strange characters in e-mails, documents or the internet? Like '???? ?? ???' or '¿¿¿¿' and others. </p>
<h3 id="heading-history-bitbyte">History bit/byte</h3>
<p>Let us start from the beginning. To represent letters or characters they must be stored in the memory / hard disk wherever. As we all know, computers in general can only store 1 and 0. 1 and 0 refer to the state of one bit. So we got one bit, which can be either active(=set)=1 or inactive(=not set)=0. 
Now 1 byte are 8 bits nearly everywhere nowadays - why? <a target="_blank" href="https://en.wikipedia.org/wiki/Byte#cite_note-Buchholz_1962-1">Because it was determined to use this to encode (store) one character</a>. From 2 states for 8 bits you end up with 2^8 = 256.</p>
<h3 id="heading-storage-representation-of-characters">Storage / representation of characters</h3>
<p>So we can store 256 different states in 1 byte. How can we express characters with this? The most and (if I remember correctly) first code chart and character encoding which was standardized for electronic communications is <a target="_blank" href="https://en.wikipedia.org/wiki/ASCII">ASCII</a>. There is a great picture at Wikipedia about it:
<img src="https://upload.wikimedia.org/wikipedia/commons/c/cf/USASCII_code_chart.png" alt="ASCII" /></p>
<p>If you focus on the upper and left area you will notice 'Bits' with the description of b1 until b7. Based on the states of these bits the corresponding character is displayed. So:</p>
<ul>
<li>All bits set to 0 will result in 'NUL'</li>
<li>All bits set to 1 will result in 'DEL'</li>
<li>0 0 0 0 1 1 0 will result in 0</li>
<li>0 0 0 1 1 1 0 will result in 8
Please note, that you have to pay attention on the order of bytes. Here I ordered them from b1 to b7, where as the table is ordering in reverse order (as the first bit in memory is the most right one).</li>
</ul>
<p>I will further use hexadecimal for byte descriptions. Hexadecimal is a numbering system which has the base number of 16. As we only got 10 numbers (0 ... 9), the first characters of the alphabet are used in addition (A ... F). You can read more about it <a target="_blank" href="https://www.sciencedirect.com/topics/engineering/hexadecimal">here</a>.</p>
<p>To keep it short, 00 is NUL where es 30 is 0. If you have got notepad++ installed, you can view a great ASCII panel by using 'Edit' -&gt; 'Character panel'. Furthermore, you can just double click to insert the character/hex/value (I use this for testing industrial devices with putty). On the german wikipedia there is a great ASCII-hex-table on the UTF-8 page:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654399385800/L9jqbMbbU.png" alt="ascii-hex-chart.png" /></p>
<h3 id="heading-special-or-control-characters">'Special' or control characters</h3>
<p>Beside the characters there was the need for some additional characters. These had been used for the control of the input by keyboard or controlling the printers. For example, FF does revere to 'Form Feed' - to eject the current page from the printer. Other famous are 'Carriage Return' and 'Line Feed' which execute 'go to position 1 of the line' and 'go to next line'. On each operation system they are interpreted a little bit different. E. g. Windows does require CRLF whereas Unix only does require LF for a line break. 
If you ever get in contact with older protocols, you will also get in contact with STX/ETX or SYN and so on which are mostly used in RS232 protocols or industrial devices. Do not ask me why they are still there (sometimes I have the feeling, that they just re-use damn old controllers), but for polling meter counters or scales within some milliseconds you do not want to use json or some other bloated protocol - you are just happy about least traffic as possible.</p>
<h3 id="heading-other-languages-other-characters-problems-arised">Other languages, other characters - problems arised</h3>
<p>After taking a close look at the characters which are visible in the ASCII character encoding you will notice that there are only US characters. No other characters like french, german, norwegian, chinese, russian, arabaic and so on characters. As the memory was very limited in the beginning and each country and big tech company (especially <a target="_blank" href="https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers">Microsoft</a>, <a target="_blank" href="https://www.ibm.com/docs/en/ztpf/1.1.0.15?topic=support-character-sets">IBM</a> and <a target="_blank" href="https://docs.oracle.com/database/121/NLSPG/ch2charset.htm#NLSPG164">Oracle</a>) did not talk to each other many new character sets have been defined. Mostly for different regions, sometimes for countries and always depending on the operating system or source application.</p>
<p>As each character set is storing the characters differently, a conversion must apply. For converting between the character sets you must know from which to which you need to convert. But not all character sets support the same characters - so when you convert one text with a specific character set to another you may loose some characters depending on the character sets used.</p>
<h3 id="heading-single-byte-and-multi-byte-character-sets">Single byte and multi byte character sets</h3>
<p>At some point the problems with the codepages and the conversions got that much that <a target="_blank" href="https://en.wikipedia.org/wiki/Unicode">Unicode</a> was born. Unicode is a 'multi-byte-character-set' (short MBCS) which does encode the characters in multiple bytes as one byte is not enough to encode the most written languages in the world (think of traditional chinese with round about 50.000 characters). There are some other MBCS like Shift-JIS, BIG5 or BG2312 beside Unicode but the most important are UTF-8, UTF-16 or UTF-32. Whereas UTF-8 is the most used character set in the internet.</p>
<p>I will further describe MBCS based on UTF-8 and in hexadecimal representation. Nearly every codepage does integrate ASCII with the original encoding. So ASCII characters are always safe. Following a short (incomplete) description:</p>
<ul>
<li>00 -&gt; 7F = One byte long, same as ASCII</li>
<li>80 -&gt; BF = Second, third or fourth byte of a multi-byte-sequence</li>
<li>C0 -&gt; C1 = In short, invalid</li>
<li>C2 -&gt; DF = Start of a 2 byte long sequence</li>
<li>E0 -&gt; EF = Start of a 3 byte long sequence</li>
<li>F0 -&gt; F4 = Start of a 4 byte long sequence
By using this declaration, it is possible to parse the encoding, detecting how many bytes together describe one character.</li>
</ul>
<p>If you want to browse UTF-8 you can also take a look <a target="_blank" href="https://www.utf8-chartable.de/">here</a>.</p>
<h3 id="heading-net-character-set-and-file-encoding">.Net character set and file encoding</h3>
<p>.Net does internally use UTF-16 to encode characters. If you want to read in a file in a different character set it is quite simple:</p>
<pre><code><span class="hljs-comment">// load encoding 850</span>
Encoding inputEncoding <span class="hljs-operator">=</span> Encoding.GetEncoding(<span class="hljs-number">850</span>);

<span class="hljs-comment">// read in file</span>
<span class="hljs-keyword">string</span> convertedText <span class="hljs-operator">=</span> File.ReadAllText(@<span class="hljs-string">"d:\test-850.txt"</span>, inputEncoding);
</code></pre><p>Nearly every class for accessing external resources is coming with a constructor which has got an overload to pass an <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.text.encoding?view=net-6.0">encoding</a>.
The list of encodings is different from operating system to operating system, to see your encodings you can use <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.text.encoding.getencodings?view=net-6.0">GetEncodings</a>. On the link you can also find a list of common encodings.</p>
<h3 id="heading-converting-bytes-strings">Converting bytes / strings</h3>
<p>If you receive data by network, from a foreign system, you also mostly have to deal with encodings. For this, following code may come in handy:</p>
<pre><code>// <span class="hljs-keyword">load</span> <span class="hljs-keyword">encoding</span> <span class="hljs-number">850</span>
<span class="hljs-keyword">Encoding</span> inputEncoding = Encoding.GetEncoding(<span class="hljs-number">850</span>);

// convert source byte array <span class="hljs-keyword">with</span> <span class="hljs-built_in">character</span> <span class="hljs-keyword">set</span> <span class="hljs-number">850</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">string</span>
<span class="hljs-keyword">string</span> convertedString = inputEncoding.GetString(someReceivedData);
</code></pre><p>Other way round:</p>
<pre><code><span class="hljs-comment">// load encoding 850</span>
Encoding inputEncoding <span class="hljs-operator">=</span> Encoding.GetEncoding(<span class="hljs-number">850</span>);

<span class="hljs-comment">// convert string to target byte array in character set 850</span>
<span class="hljs-keyword">byte</span>[] convertedBytes <span class="hljs-operator">=</span> inputEncoding.GetBytes(convertedString);
</code></pre><p>If you are required/or interested in getting the number of bytes in a string you can also use the GetByteCount() method.</p>
<p>Thank you for reading!</p>
<h3 id="heading-credits">Credits</h3>
<p>Photo by <a target="_blank" href="https://unsplash.com/@nshuman1291?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Nathaniel Shuman</a> on <a target="_blank" href="https://unsplash.com/s/photos/letters?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
]]></content:encoded></item><item><title><![CDATA[ORA-39150 & ORA-08186 using expdp in 19.12.0.0.0]]></title><description><![CDATA[Today I got an email from one of our colleagues that the daily datapump which we are executing with the parameter 'flashback_time=systimestamp' is suddenly failing.
The log files only show the following and alert log is empty:
Connected to: Oracle Da...]]></description><link>https://blog.sigterm.eu/ora-39150-and-ora-08186-using-expdp-in-1912000</link><guid isPermaLink="true">https://blog.sigterm.eu/ora-39150-and-ora-08186-using-expdp-in-1912000</guid><category><![CDATA[Oracle]]></category><category><![CDATA[Export]]></category><category><![CDATA[datapump]]></category><category><![CDATA[expdp]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Thu, 02 Jun 2022 18:09:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/heNwUmEtZzo/upload/v1654505616155/ONGzwD_5A.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today I got an email from one of our colleagues that the daily datapump which we are executing with the parameter 'flashback_time=systimestamp' is suddenly failing.</p>
<p>The log files only show the following and alert log is empty:</p>
<pre><code><span class="hljs-attr">Connected to:</span> <span class="hljs-string">Oracle</span> <span class="hljs-string">Database</span> <span class="hljs-string">19c</span> <span class="hljs-string">Standard</span> <span class="hljs-string">Edition</span> <span class="hljs-number">2</span> <span class="hljs-string">Release</span> <span class="hljs-number">19.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span> <span class="hljs-bullet">-</span> <span class="hljs-string">Production</span>
<span class="hljs-attr">ORA-39150:</span> <span class="hljs-string">bad</span> <span class="hljs-string">flashback</span> <span class="hljs-string">time</span>
<span class="hljs-attr">ORA-08186:</span> <span class="hljs-string">invalid</span> <span class="hljs-string">timestamp</span> <span class="hljs-string">specified</span>
</code></pre><p>Metalink from Oracle just telling us that the timestamp format is wrong, and we do not need to worry about timestamp format if we use systimestamp.</p>
<p>After digging around a little bit, I noticed that the times in log files suddenly 'jumped' without any notice about a time drift, neither from windows nor oracle (and oracle is very verbose in logging this).</p>
<p>Restarting the whole database got rid of the error. The reason for all of this seems to be that the customer changed the region format of the server without restarting the database. However, I have not tried reproducing this in a lab, but it seems to be the only change which was done on the server in the last days.</p>
<p>As a side note, if you are questioning yourself why we are running a daily datapump export: Naturally we are running an additional recovery manager backup and we always advise the customers to use some solid tested robust fancy backup software with a dedicated database agent for handling the database backup correctly with monitoring and so on and on... BUT if you have got a big application database and someone started a wrongly configured cleanup operation, naturally without any verification in the dev environment, or 'accidently dropping' the wrong table / deleting single rows, you do not want to role backup a whole database to a specific point in time, sometimes not even a specific table. Depending on the type of data (low change rate, e.g. master data) you can recover them sometimes much faster from dump instead of recovering from backup. 
Another point... we also experienced people who 'lost' their rman backup or some files and you end up with an old backup or need to contact oracle support for an inconsistent recovery because of the missing files. Then a datapump files is also coming in handy...</p>
]]></content:encoded></item><item><title><![CDATA[Converting hex/bytes/int drama got a happy end]]></title><description><![CDATA[You won't believe how happy I have been,  when I noticed the new BitConverter class in .Net. Finally, stop taking some stupid helper class around with you, just for converting byte to hex or other types and vice versa for example for debug logging. N...]]></description><link>https://blog.sigterm.eu/converting-hexbytesint-drama-got-a-happy-end</link><guid isPermaLink="true">https://blog.sigterm.eu/converting-hexbytesint-drama-got-a-happy-end</guid><category><![CDATA[C#]]></category><category><![CDATA[convert]]></category><category><![CDATA[bytes]]></category><category><![CDATA[hex ]]></category><category><![CDATA[bitconverter]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Thu, 02 Jun 2022 03:17:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654505484402/jgOzEw3hG.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You won't believe how happy I have been,  when I noticed the new <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.bitconverter?f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.BitConverter)%3Bk(DevLang-csharp)%26rd%3Dtrue&amp;view=net-6.0">BitConverter</a> class in .Net. Finally, stop taking some stupid helper class around with you, just for converting byte to hex or other types and vice versa for example for debug logging. Now mostly a simple one-liner!</p>
<h3 id="heading-we-take-a-very-short-look-into-bitconverter">We take a very short look into BitConverter</h3>
<h4 id="heading-byte-to-hex-dump">byte to hex dump</h4>
<p><a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.bitconverter.tostring?f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.BitConverter.ToString)%3Bk(DevLang-csharp)%26rd%3Dtrue&amp;view=net-6.0">BitConverter.ToString</a></p>
<pre><code><span class="hljs-comment">// 104 is the int representation of the char 'h', hex '68'</span>
<span class="hljs-comment">// 105 is the int representation of the char 'i', hex '69'</span>
<span class="hljs-keyword">byte</span>[] someByteArr <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">2</span>] {<span class="hljs-number">104</span>,<span class="hljs-number">105</span>}; 

<span class="hljs-keyword">string</span> hexDump <span class="hljs-operator">=</span> BitConverter.ToString(someByteArr);
Console.WriteLine(hexDump);
<span class="hljs-comment">// output: 68-69</span>
</code></pre><p>There are numerous <a target="_blank" href="https://en.wikipedia.org/wiki/Hexadecimal">hexadecimal</a> notations. For example: 68-69, 0x68 0x69, \x68 \x69 and so on...
If Hexadecimal is unknown to you, I strongly recommend reading the article from Wikipedia as it will improve your understanding massively. </p>
<h4 id="heading-bytes-to-int32-exemplary">bytes to int32 (exemplary)</h4>
<p>Simply:</p>
<pre><code><span class="hljs-keyword">byte</span>[] someByteArr <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">2</span>] {<span class="hljs-number">132</span>,<span class="hljs-number">1</span>};

short result <span class="hljs-operator">=</span> BitConverter.ToInt16(someByteArr);
Console.WriteLine(result);
<span class="hljs-comment">// output: 388</span>
</code></pre><p>When converting this way, please remind the byte required byte array length (e.g., 2 bytes for int16/4bytes for int32/8bytes for int64) and the order of bytes you received (host byte order or network byte order / lowHIGH or HIGHlow). </p>
<p>Some little history: In general, it is called 'endianness', the order of the bytes of a word in the memory, where we have big-endian and little-endian. In the beginning the mainframes dominated the world which all used big-endianness. When the personal computer came up it switched to little-endianness. However, the network is still mostly big-endianness because the IETF RFCs (public declarations of protocols) use them. You can read more about this at <a target="_blank" href="https://en.wikipedia.org/wiki/Endianness">Wikipedia</a>.
You can test endianness yourself if you simply switch the bytes in the upper array:</p>
<pre><code><span class="hljs-keyword">byte</span>[] someByteArr <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">2</span>] {<span class="hljs-number">1</span>,<span class="hljs-number">132</span>};

short result <span class="hljs-operator">=</span> BitConverter.ToInt16(someByteArr);
Console.WriteLine(result);
<span class="hljs-comment">// output: -31743</span>
</code></pre><p>The framework itself does implement <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.net.ipaddress.hosttonetworkorder?view=net-6.0">IPAddress.HostToNetworkOrder</a> and <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.net.ipaddress.networktohostorder?view=net-6.0">IPAddress.NetworkToHostOrder</a> for switching between the endiannesses. As an alternative, just use <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.array.reverse?view=net-6.0">Array.Reverse</a>.</p>
<h4 id="heading-converting-one-byte-to-int-representation">Converting one byte to int representation</h4>
<p>The conversion is still using the good old <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.convert?f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.Convert)%3Bk(DevLang-csharp)%26rd%3Dtrue&amp;view=net-6.0">Convert</a> class. Where we simply can convert one byte to the corresponding representation. This is a hard conversion, so exceptions may and often happen. We are just converting the representation, not dealing with the real 'data'. 
For example, a byte can be also expressed using an int as used in above examples for the byte array initialization:</p>
<pre><code><span class="hljs-keyword">byte</span>[] someByteArr <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">2</span>] {<span class="hljs-number">132</span>,<span class="hljs-number">1</span>};

<span class="hljs-keyword">int</span> result <span class="hljs-operator">=</span> Convert.ToInt32(someByteArr[<span class="hljs-number">0</span>]);
Console.WriteLine(result);
<span class="hljs-comment">// output: 132</span>

result <span class="hljs-operator">=</span> Convert.ToInt32(someByteArr[<span class="hljs-number">1</span>]);
Console.WriteLine(result);
<span class="hljs-comment">// output: 1</span>
</code></pre><h3 id="heading-just-taking-an-exit-before-the-end-to-go-the-way-through-unsignedsigned">Just taking an exit before the end to go the way through unsigned/signed</h3>
<p>Here we will use integer / int here. uint stands for unsigned integer whereas int is for signed integer. Unsigned integers can only have positive values and signed also negative. 
In the memory itself however, the occupied space is the same so a 'trick' is used to accomplish this resulting in different ranges:
int    -2,147,483,648 to 2,147,483,647
uint    0 to 4,294,967,295
You can read more about this <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types">here</a>.</p>
<p>As the data in the memory is different, the type is important for casting. If the wrong type is used an 'overflow' may happen which does result in wrong interpretation of the data.</p>
<p>I will not dive deep into the memory storage itself, there are much better articles about that for example at Wikipedia, which you already find referenced in this article.</p>
<h3 id="heading-credits">Credits</h3>
<p>Photo by <a target="_blank" href="https://unsplash.com/@mostafa_meraji?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">mostafa meraji</a> on <a target="_blank" href="https://unsplash.com/s/photos/drama?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
]]></content:encoded></item><item><title><![CDATA[Exceptions catching / handling / throwing]]></title><description><![CDATA[When I started coding c# over more than 15 years ago it was common practice to use Exceptions for handling errors, also internally.
So, instead of returning pure error messages with indicators if a method suceeded (see my Tuples article here), Except...]]></description><link>https://blog.sigterm.eu/exceptions-catching-handling-throwing</link><guid isPermaLink="true">https://blog.sigterm.eu/exceptions-catching-handling-throwing</guid><category><![CDATA[C#]]></category><category><![CDATA[error handling]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Sun, 29 May 2022 04:15:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654491502432/LrgAEju-2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I started coding c# over more than 15 years ago it was common practice to use Exceptions for handling errors, also internally.</p>
<p>So, instead of returning pure error messages with indicators if a method suceeded (see my Tuples article here), Exceptions had been thrown. </p>
<p>Now, Exceptions are not anymore that nice when it comes to:</p>
<ul>
<li>program flow (some exception is thrown somewhere and catched 4 times up the call stack)</li>
<li>they are 'cost intensive' - which does mean they require some ressources</li>
<li>call stack or inner exceptions are lost if not handled correctly</li>
</ul>
<p>But they are great to use when something really worse happend for your application and you cannot continue.</p>
<h2 id="heading-short-introduction">Short introduction</h2>
<p><a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/standard/exceptions/">Exceptions</a>?</p>
<p>When an exception is thrown, the following program code is not executed anymore (beside there is a finally block) until it is catched. If it is not catched somewhere, the program is terminated.</p>
<pre><code><span class="hljs-comment">// we just want one method throwing the exception</span>
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ExcSample</span>(<span class="hljs-params"></span>)</span>
{
  <span class="hljs-keyword">throw</span> Exception(<span class="hljs-string">"foo"</span>);
}

<span class="hljs-comment">// </span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"></span>)</span>
{
   <span class="hljs-comment">// will result in termination of the program as no exception will be catched</span>
   ExcSample();

   <span class="hljs-comment">// will catch the exception in the catch block and write the message to console</span>
   <span class="hljs-keyword">try</span>
   {
      ExcSample();
   }
   <span class="hljs-keyword">catch</span>(Exception exc)
   {
      Console.WriteLine(<span class="hljs-string">$"Error occured: <span class="hljs-subst">{exc.Message}</span>"</span>);
   }

   <span class="hljs-comment">// example with finally block</span>
   <span class="hljs-keyword">try</span>
   {
      ExcSample();
   }
   <span class="hljs-keyword">catch</span>(Exception exc)
   {
      Console.WriteLine(<span class="hljs-string">$"Error occured: <span class="hljs-subst">{exc.Message}</span>"</span>);
   }
   <span class="hljs-keyword">finally</span> 
   {
      <span class="hljs-comment">// code here would be always executed: if an exception does occur or if not</span>
   }

   <span class="hljs-comment">// also possible, only finally</span>
   <span class="hljs-keyword">try</span>
   {
      ExcSample();
   }
   <span class="hljs-keyword">finally</span> 
   {
      <span class="hljs-comment">// code here would be always executed: if an exception does occur or if not</span>
   }
}
</code></pre><h2 id="heading-custom-or-user-defined-exceptions">Custom or user-defined exceptions</h2>
<p><a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/standard/exceptions/how-to-create-user-defined-exceptions">Custom or user-defined exceptions</a> are exceptions which have been created by yourself. The decision to create own exceptions may be due to additional requirements for the Exception itself (e. g. <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/standard/exceptions/how-to-create-localized-exception-messages">localization</a> or for logic operations where no existing Exception may fit your needs.</p>
<p>Exceptions can be simply created by deriving your new Exception class from the base class or any other Exception class:</p>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyOwnException</span> : <span class="hljs-title">Exception</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">uint</span> MyInternalErrorCode { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyOwnException</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> errorCode</span>)</span>
    {
        MyInternalErrorCode = errorCode;
    }

    <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;inheritdoc /&gt;</span></span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyOwnException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>? message</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">message</span>)</span>
    {
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyOwnException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>? message, <span class="hljs-keyword">uint</span> myInternalErrorCode</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">message</span>)</span>
    {
        MyInternalErrorCode = myInternalErrorCode;
    }

    <span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;inheritdoc /&gt;</span></span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyOwnException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>? message, Exception? innerException</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">message, innerException</span>)</span>
    {
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyOwnException</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>? message, Exception? innerException, <span class="hljs-keyword">uint</span> myInternalErrorCode</span>) : <span class="hljs-title">base</span>(<span class="hljs-params">message, innerException</span>)</span>
    {
        MyInternalErrorCode = myInternalErrorCode;
    }
}
</code></pre><h2 id="heading-catching-multiple-exceptions">Catching multiple exceptions</h2>
<p>Please refer to my article about when</p>
<h2 id="heading-catching-unhandled-exceptions">Catching unhandled exceptions</h2>
<p>To catch all unhandled exceptions in your program, e. g. for logging it to a file instead of default logging facilities it is possible to subscribe to some even:</p>
<pre><code>static async Task Main(<span class="hljs-keyword">string</span>[] args)
{
    <span class="hljs-comment">// subscribe to event for all unhandled eceptions</span>
    AppDomain.CurrentDomain.UnhandledException <span class="hljs-operator">+</span><span class="hljs-operator">=</span> ApplicationUnhandledException;
    <span class="hljs-comment">// rest of code...</span>
}

<span class="hljs-comment">// event handler</span>
<span class="hljs-keyword">private</span> static void ApplicationUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    <span class="hljs-comment">// log the exception for example</span>
    Logger.Fatal((Exception) e.ExceptionObject, <span class="hljs-string">"Unhandled exception: {0}"</span>, e.ExceptionObject);
}
</code></pre><p>Using Tasks the above will not work, but the <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler?redirectedfrom=MSDN&amp;view=net-6.0/9">TaskScheduler class</a> does provide an <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception?view=net-6.0">Event UnobservedTaskException</a> which we can use in this case.</p>
<h3 id="heading-credits">Credits</h3>
<p>Photo by <a target="_blank" href="https://unsplash.com/@dogflirt?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Anthony Duran</a> on <a target="_blank" href="https://unsplash.com/s/photos/catch?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
]]></content:encoded></item><item><title><![CDATA[Tuples, tuples... value tuples!]]></title><description><![CDATA[Introduction
In the very first beginning of tuples in c# I firstly skipped it, because the readability had been not what I though of creating readable code.
Example from MSDN:
(bool, string) t1 = (true, "");
Console.WriteLine($"Tuple with value {t1.I...]]></description><link>https://blog.sigterm.eu/tuples-tuples-value-tuples</link><guid isPermaLink="true">https://blog.sigterm.eu/tuples-tuples-value-tuples</guid><category><![CDATA[C#]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Sun, 29 May 2022 04:02:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/hTv8aaPziOQ/upload/v1654505562317/_W167pD1t.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In the very first beginning of tuples in c# I firstly skipped it, because the readability had been not what I though of creating readable code.</p>
<p>Example from <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples">MSDN</a>:</p>
<pre><code class="lang-plaintext">(bool, string) t1 = (true, "");
Console.WriteLine($"Tuple with value {t1.Item1} and string {t1.Item2}.");
</code></pre>
<p>When using tuples with more than 2 variables it was always about remembering which variable is which item.</p>
<p>With the introduction of ValueTuples this changed. Now it is possible to assign a 'name' to each tuple variable:</p>
<pre><code class="lang-plaintext">(bool rc, string error) t2 = (true, "");
Console.WriteLine($"Tuple with value {t2.rc} and string {t2.error}.");
</code></pre>
<h2 id="heading-where-for">Where for?</h2>
<p>Now where should I use tuples?</p>
<h3 id="heading-data-storage">Data storage</h3>
<p>In general they can be used everywhere. However imho for complex data, the code readability will be worse, if you use it for storing big data instead of using classes. Let me show you an example:</p>
<pre><code class="lang-plaintext">(string FirstName, string LastName, DateTime BirthDay) person
</code></pre>
<p>Using it together with a list will result in:</p>
<pre><code class="lang-plaintext">List&lt;(string FirstName, string LastName, DateTime BirthDay) person&gt;
</code></pre>
<p>In this case using a dedicated data class should be prefered as the readability greatly improves and the data class can be extended with additional methods.</p>
<p>But for temporarily storing small data constructs, where Dictionaries, Collections or Hastables do not bring in any benefit, they are great also!</p>
<h3 id="heading-method-return-type">Method return type</h3>
<p>That is the point where we switched to value tuples and now using them heavily. Instead of using out variables or ref variables for providing the error messages to the calling method we switched to tuples. Please note, that this is specific about requirements of returning an error - it is NOT a recommendation of when to use return values or Exceptions. See for example <a target="_blank" href="https://stackoverflow.com/questions/99683/which-and-why-do-you-prefer-exceptions-or-return-codes">language agnostic - Which, and why, do you prefer Exceptions or Return codes? - Stack Overflow</a></p>
<p>Previously:</p>
<pre><code class="lang-plaintext">string error = "";
bool rc = FirstMethod(ref string error);
if(!rc)
  _logger.Error(error);

rc = SecondMethod(ref string error);
if(!rc)
  _logger.Error(error);
</code></pre>
<p>Now with tuples:</p>
<pre><code class="lang-plaintext">(bool success, string error) callRc = FirstMethod();
if(!callRc.success)
  _logger.Error(callRc.error);

callRc = SecondMethod();
if(!callRc.success)
  _logger.Error(callRc.error);
</code></pre>
<p>It can be easily extended with a more complex tuple for also handling an additional variable providing e. g. data from the called method which does work great together with <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references">nullable</a>:</p>
<pre><code class="lang-plaintext">(bool success, string error, string[] lines) callRc = LoadFile();
if(!callRc.success)
{
   _logger.Error(callRc.error);
   return;
}
// process data using callRc.lines ...
</code></pre>
<h2 id="heading-var">var</h2>
<p>Instead of specifying the return values each on it's own:</p>
<pre><code class="lang-plaintext">(bool success, string error) callRc = FirstMethod();
</code></pre>
<p>We can also use var which does work perfect with IntelliSense:</p>
<pre><code class="lang-plaintext">var callRc = FirstMethod();
</code></pre>
<h2 id="heading-deconstruct">Deconstruct</h2>
<p>And last but not least, we can also 'desconstruct' the tuple and direct access the single variables:</p>
<pre><code class="lang-plaintext">(bool success, string error) = FirstMethod();
if(!success)
  _logger.Error(error);

// use them again but without declaration 
(success, error) = SecondMethod();
if(!success)
  _logger.Error(error);
</code></pre>
<h2 id="heading-naming-conventions">Naming conventions</h2>
<p>Internally we decided to use the following typing conventions with tuples:</p>
<ul>
<li><p>For return tuples, we use tuple variables in lowerCase</p>
</li>
<li><p>For data tuples, we use tuple variables in UpperCase</p>
</li>
</ul>
<p>Last but not least, please remind yourself that tuples are value types!</p>
]]></content:encoded></item><item><title><![CDATA[Finally.... WHEN! (or exception filters)]]></title><description><![CDATA[With the introduction of c# 6 (no, not .net 6) the when keyword arrived... finally/luckily!
Why I am so happy about that?
When we talk about using external ressources, we talk about exceptions which may happen... They can occure everywhere... for exa...]]></description><link>https://blog.sigterm.eu/finally-when-or-exception-filters</link><guid isPermaLink="true">https://blog.sigterm.eu/finally-when-or-exception-filters</guid><category><![CDATA[C#]]></category><category><![CDATA[error handling]]></category><dc:creator><![CDATA[Dominik Schischma]]></dc:creator><pubDate>Sun, 29 May 2022 03:37:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1654270094850/DzNLCwIxX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With the introduction of <a target="_blank" href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/october/csharp-the-new-and-improved-csharp-6-0">c# 6</a> (no, not .net 6) the <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/when">when</a> keyword arrived... finally/luckily!</p>
<p>Why I am so happy about that?
When we talk about using external ressources, we talk about exceptions which may happen... They can occure everywhere... for example reading a file, creating a connection and so on. </p>
<h3 id="heading-before-when">Before when</h3>
<p>What I came accross in my developers life are the following examples:</p>
<pre><code><span class="hljs-comment">// instead of multiple catch blocks for specific exceptions, just the Exception base class is catched</span>
<span class="hljs-keyword">try</span> { }
<span class="hljs-keyword">catch</span> (Exception ex) {}

<span class="hljs-comment">// sometimes afterwards filtered</span>
<span class="hljs-keyword">try</span> { }
<span class="hljs-keyword">catch</span> (Exception ex) 
{
   <span class="hljs-keyword">if</span> (ex.Message.Contains(<span class="hljs-string">"..."</span>)) { }
   <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span>;
}

<span class="hljs-comment">// or filtering for some properties of the exception</span>
<span class="hljs-keyword">catch</span> (HttpRequestException exc) 
{
   <span class="hljs-keyword">if</span>(exc.StatusCode is HttpStatusCode.BadGateway)
   { }
   <span class="hljs-keyword">else</span> 
     <span class="hljs-keyword">throw</span>;
}
</code></pre><p>Now catching the base class/general exception is <a target="_blank" href="https://stackoverflow.com/questions/426346/is-this-a-bad-practice-to-catch-a-non-specific-exception-such-as-system-exception">bad practice</a> or <a target="_blank" href="https://stackoverflow.com/questions/1742940/why-not-catch-general-exceptions">here</a>.</p>
<p>The other problem is the <a target="_blank" href="https://en.wikipedia.org/wiki/Call_stack#Unwinding">stack unwinding</a>, which is happening as soon as a catch block is entered. So every time an exception is not handled, but rethrown from the catch block, stack unwinding is happening, which will not only be done multiple times if the exception is rethrown, but you also loose your stack trace (<a target="_blank" href="https://stackoverflow.com/questions/57383/how-to-rethrow-innerexception-without-losing-stack-trace-in-c">beside you call another method again</a>).</p>
<h3 id="heading-using-when">Using when</h3>
<p>Using 'when', we can filter with any kind of bool logic without any stack unwinding happening:</p>
<pre><code><span class="hljs-keyword">catch</span> (HttpRequestException exc) when (exc.StatusCode is HttpStatusCode.BadGateway)
</code></pre><p>Furthermore, we can easily improve code readability by combining catch blocks which do the same:</p>
<pre><code><span class="hljs-keyword">catch</span> (UnauthorizedAccessException exc)
{
    <span class="hljs-keyword">return</span> (<span class="hljs-literal">false</span>, exc.Message);
}
<span class="hljs-keyword">catch</span> (SecurityException exc)
{
    <span class="hljs-keyword">return</span> (<span class="hljs-literal">false</span>, exc.Message);
}
<span class="hljs-keyword">catch</span> (IOException exc)
{
    <span class="hljs-keyword">return</span> (<span class="hljs-literal">false</span>, exc.Message);
}
</code></pre><p>All three catch clauses do the same but instead of 4 lines we used 12. Now, using 'when' we can easily rewrite this to:</p>
<pre><code><span class="hljs-keyword">catch</span> (Exception exc) when (exc is UnauthorizedAccessException or SecurityException or IOException)
{
    <span class="hljs-keyword">return</span> (<span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>, exc.Message);
}
</code></pre><p>If you require specific exception objects, eg. the Socket Errorcode, you still need to catch the SocketException itself.</p>
]]></content:encoded></item></channel></rss>