Category: projects

NetPackageAnalyzer- idea –part 1

I wanted to have a tool that can analyze a C# solution with all the dependencies ( project relations, packages, commits)

It generates a graph of the dependencies for

  • the packages of your solution ( and see when the major version of a package differs between projects)

  • the projects of your solution.
  • the project dependencies of each project.

Along with the graph, it also generates

  • a report for the commits of the solution per years.

  • a report for outdated/deprecated packages per solution.
  • building blocks for the solution – you can start from here to understand the solution

If you want to see how it looks like, you can see how he analyses himself at Analyzer

Comparing EFCore Database Providers-part-1

IDName
1 Part 1
2 Part 2
3 Part 3

I wanted to see if there are any differences in EFCore database providers listed at 

https://learn.microsoft.com/en-us/ef/core/providers/?tabs=dotnet-core-cli

I want to test the capabilities for each one within a standard choice of tables , in order to know the capabilities

I choose only those that have a version for current STS / LTS , whatever it is current.

( I am particularly interested in SqlServer vs Sqlite )

Problem 1: Conflicting namespaces

For MySql – there are 2 providers , Pomelo.EntityFrameworkCore.MySql  and MySql.EntityFrameworkCore  . Both have the same namespace and class for .UseMySql  ( and other stuff)

So how to do it ? Fortunately, nuget supports alias .

So the code in csproj is

<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" Aliases="PomeloEFMySql"  />
<PackageReference Include="MySqlConnector" Version="2.2.5" Aliases="MySqlConnect" />

<PackageReference Include="MySql.EntityFrameworkCore" Version="7.0.5" Aliases="MySqlEFOracle" />
<PackageReference Include="MySql.Data" Version="8.1.0" Aliases="OracleMySql"/>
		

And the code in global.cs

extern alias OracleMySql;

extern alias PomeloEFMySql;
extern alias MySqlConnect;

global using MySqlCNBOracle = MySqlEFOracle.Microsoft.EntityFrameworkCore.MySQLDbContextOptionsExtensions;
global using MySqlOracle = OracleMySql.MySql.Data.MySqlClient;
global using MySqlEF = MySqlEFOracle::Microsoft.EntityFrameworkCore;
 
global using PomeloCN= MySqlConnect::MySqlConnector;
global using PomeloEF = PomeloEFMySql::Microsoft.EntityFrameworkCore;
global using PomeloMySqlCNB =PomeloEFMySql::Microsoft.EntityFrameworkCore.MySqlDbContextOptionsBuilderExtensions;

And the code to use it

case EFCoreProvider.Pomelo_EntityFrameworkCore_MySql:

    var serverVersion = PomeloEF.ServerVersion.AutoDetect(con);
    StepExecution.Current.Comment("version " + serverVersion.ToString());
    PomeloMySqlCNB.UseMySql(builder,con, serverVersion)
        .EnableSensitiveDataLogging()
        .EnableDetailedErrors();
    
    break;
case EFCoreProvider.MySql_EntityFrameworkCore:
    MySqlCNBOracle.UseMySQL(builder,con);
    break;

You can find the results at https://github.com/ignatandrei/TestEFCoreDatabaseProviders and https://ignatandrei.github.io/TestEFCoreDatabaseProviders/

Problem 2 : Conflict on container ports

When a container is started for a test it works on a port ( 1433 for SqlServer). When a new test arrives ( with new tables ) , it cannot be on the same port . So the docker containers must be disposed when the test finishes. Also , the tests must be done in serial, not in paralel.

For parallelism, it is simple ( LightBDD + XUnit)

[assembly: CollectionBehavior(DisableTestParallelization = true)]
[assembly: ClassCollectionBehavior(AllowTestParallelization = false)]

For disposing, can use IScenarioTearDown (LightBDD) or IAsyncLifetime (XUnit)

NetCoreUsefullEndpoints-part 8- adding start date

In my NuGet NetCoreUsefullEndpoints package  I have had already registered the actual date as

var rh = route.MapGet(“api/usefull/dateUTC”, (HttpContext httpContext) =>
            {
                return Results.Ok(DateTime.UtcNow);
            });

Now I want to register also the start date – the date where the application has been started.

1. How to do this  ?

2. What will be the route ?

For 1 can be a static constructor or, better , the singleton in C# :

private static DateTime startDateUTC = DateTime.UtcNow;

For 2 it is more complicated

My solution ( just break compatibility, since I have not a v1 and v2) was the following

var rh = route.MapGet(“api/usefull/date/startUTC”, (HttpContext httpContext) =>
{
     return Results.Ok(startDateUTC);
});

var rhUTC = route.MapGet(“api/usefull/date/nowUTC/”,
     (HttpContext httpContext) =>
     {
         return TypedResults.Ok(DateTime.UtcNow);
     });

rhUTC.AddDefault(corsPolicy, authorization);

So now I have same routing api/usefull/date

NetCoreUsefullEndpoints–part 7–restart application

In order to do the shutdown, I have added the following extension

public static CancellationTokenSource cts=new ();

public static void MapShutdown(this IEndpointRouteBuilder route, string? corsPolicy = null, string[]? authorization = null)
        {
            ArgumentNullException.ThrowIfNull(route);
            var rh = route.MapPost(“api/usefull/shutdown/”,
                (HttpContext httpContext) =>
                {
                    var h= cts.Token.GetHashCode();
                    cts?.Cancel();                   
                    return h;
                   
                });

           rh.AddDefault(corsPolicy, authorization);

        }

This code defines a static field called “cts” in the “UsefullExtensions” class. “cts” is an instance of the “CancellationTokenSource” class, which is used to create a CancellationToken that can be used to stop the application gracefully.

The “MapShutdown” method is an extension method for IEndpointRouteBuilder that creates a new endpoint for a POST request to the “api/usefull/shutdown/” URL. When the request is received, the method cancels the “cts” CancellationTokenSource if it is not null, and returns the hash code of the CancellationToken. The method also sets the “corsPolicy” and “authorization” parameters for the endpoint.

You can call with

app.MapUsefullAll();

or with

app.MapShutdown

Anyway , the runAsync should be modified with

await app.RunAsync(UsefullExtensions.UsefullExtensions.cts.Token);

The “RunAsync” method of the “app” object is used to start the application and listen for incoming requests. The method takes a CancellationToken as an argument, which allows the application to be stopped gracefully by cancelling the token. In this case, the token is provided by the “cts” field of the “UsefullExtensions” class. The code uses the “await” keyword to wait for the task returned by “RunAsync” to complete before continuing.

DIForFunctions – Improving constructor–part 5

I have received a suggestion : what if we just put into constructor what we need , and everything else ( such as ILogger ) are into fields ?

The Roslyn Source Code Generator will generate a constructor that calls the this constructor  and will assign fields needed.

Let’s give an example : We wrote

public partial class TestDIFunctionAdvWithConstructor2Args
    {
        [RSCG_FunctionsWithDI_Base.FromServices]
        private TestDI1 NewTestDI1;

       public TestDI2 NewTestDI2 { get; set; }

       public readonly TestDI3 myTestDI3;

       private TestDIFunctionAdvWithConstructor2Args(TestDI3 test, TestDI2 a)
        {
            myTestDI3 = test;
            NewTestDI2 = a;
        }

   }

and the generator will generate a new constructor with the required  field

public partial class TestDIFunctionAdvWithConstructor2Args
{
public TestDIFunctionAdvWithConstructor2Args  
(TestDI3 test, TestDI2 a, TestDI1 _NewTestDI1) : this (test,a)
{
this.NewTestDI1 = _NewTestDI1;
}//end constructor

}//class

The code is non trivial  – to find if a constructor exists, take his fields, generate new constructor with all fields.

But , as anything in IT , it is doable .

Record visitors- work on issues–part 7

Now it is time to solve some issues  There were 12 issues written by me – you can see here:

https://github.com/ignatandrei/RecordVisitors/issues?q=is%3Aissue+is%3Aclosed

Between the most important:

  1. Improve readme.md with more links and explanations for potential programmer and contributors
  2. Write version in static constructor – to know about the version, if some issue occurs
  3. Added custom link  lastvisitors/minutes/{time:int} to see the latest visitors in a time frame
  4. Add read the docs site https://record-visitors.readthedocs.io/en/latest/
  5. Modification on the interfaces – replacing FUNC property with a real Func

There seems little – but it takes a while.

The links for the project are now

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.