Sunday, August 23, 2020

Creating first Blazor app with Experimental Mobile Blazor Bindings and Blazor Hybrid templates

 MSDN Article as of mid of 2020: https://docs.microsoft.com/en-us/mobile-blazor-bindings/get-started

I have noticed that installing the project templates is slightly different from what is mentioned in the above article.

Using mobileblazorbindings template


dotnet new mobileblazorbindings -o MyMobileBlazorApp


Using blazorhybrid template


dotnet new blazorhybrid -o MyHybridApp




Preview - Windows App



Saturday, August 22, 2020

SQL Script to clean all non system database Objects


USE [<My Database>]

/* Drop all non-system stored procs */

DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 ORDER BY [name])

WHILE @name is not null
BEGIN
    SELECT @SQL = 'DROP PROCEDURE [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped Procedure: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

/* Drop all views */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 ORDER BY [name])

WHILE @name IS NOT NULL
BEGIN
    SELECT @SQL = 'DROP VIEW [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped View: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

/* Drop all functions */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 ORDER BY [name])

WHILE @name IS NOT NULL
BEGIN
    SELECT @SQL = 'DROP FUNCTION [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped Function: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

/* Drop all Foreign Key constraints */
DECLARE @name VARCHAR(128)
DECLARE @constraint VARCHAR(254)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)

WHILE @name is not null
BEGIN
    SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    WHILE @constraint IS NOT NULL
    BEGIN
        SELECT @SQL = 'ALTER TABLE [dbo].[' + RTRIM(@name) +'] DROP CONSTRAINT [' + RTRIM(@constraint) +']'
        EXEC (@SQL)
        PRINT 'Dropped FK Constraint: ' + @constraint + ' on ' + @name
        SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND CONSTRAINT_NAME <> @constraint AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    END
SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
END
GO

/* Drop all Primary Key constraints */
DECLARE @name VARCHAR(128)
DECLARE @constraint VARCHAR(254)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)

WHILE @name IS NOT NULL
BEGIN
    SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    WHILE @constraint is not null
    BEGIN
        SELECT @SQL = 'ALTER TABLE [dbo].[' + RTRIM(@name) +'] DROP CONSTRAINT [' + RTRIM(@constraint)+']'
        EXEC (@SQL)
        PRINT 'Dropped PK Constraint: ' + @constraint + ' on ' + @name
        SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME <> @constraint AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    END
SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
END
GO

/* Drop all tables */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])

WHILE @name IS NOT NULL
BEGIN
    SELECT @SQL = 'DROP TABLE [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped Table: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

 




Tuesday, July 28, 2020

What is the difference between asynchronous programming and multi-threading?

This misunderstanding is extremely common. Many people are taught that multithreading and asynchrony are the same things, but they are not.

An analogy usually helps. You are cooking in a restaurant. An order comes in for eggs and toast.
  • Synchronous: you cook the eggs, then you cook the toast.
  • Asynchronous, single-threaded: you start the eggs cooking and set a timer. You start the toast cooking and set a timer. While they are both cooking, you clean the kitchen. When the timers go off, you take the eggs off the heat and the toast out of the toaster and serve them.
  • Asynchronous, multithreaded: you hire two more cooks, one to cook eggs and one to cook toast. Now you have the problem of coordinating the cooks so that they do not conflict with each other in the kitchen when sharing resources. And you have to pay for them.

Now, does it make sense that multithreading is only one kind of synchrony?

Threading is about workers; asynchrony is about tasks. In multithreaded workflows, you assign tasks to workers. In asynchronous single-threaded workflows, you have a graph of tasks where some tasks depend on the results of others; as each task completes it invokes the code that schedules the next task that can run, given the results of the just-completed task. But you (hopefully) only need one worker to perform all the tasks, not one worker per task.

It will help to realize that many tasks are not processor-bound. For processor-bound tasks, it makes sense to hire as many workers (threads) as there are processors, assign one task to each worker, assign one processor to each worker, and have each processor do the job of nothing else but compute the result as quickly as possible. But for tasks that are not waiting on a processor, you don't need to assign a worker at all. You just wait for the message to arrive that the result is available and do something else while you're waiting. When that message arrives, then you can schedule the continuation of the completed task as the next thing on your to-do list to check off.

So let's look at Jon's example in more detail. What happens?
  • Someone invokes DisplayWebSiteLength. Who? We don't care.
  • It sets a label, creates a client, and asks the client to fetch something. The client returns an object representing the task of fetching something. That task is in progress.
  • Is it in progress on another thread? Probably not. Read Stephen's article on why there is no thread.
  • Now we await the task. What happens? We check to see if the task has been completed between the time we created it, and we awaited it. If yes, then we fetch the result and keep running. Let's suppose it has not been completed. We sign up the remainder of this method as the continuation of that task and return.
  • Now control has returned to the caller. What does it do? Whatever it wants.
  • Now suppose the task completes. How did it do that? Maybe it was running on another thread, or maybe the caller that we just returned to allowed it to run to completion on the current thread. Regardless, we now have a completed task.
  • The completed task asks the correct thread -- again, likely the only thread -- to run the continuation of the task.
  • Control passes immediately back into the method we just left at the point of the await. Now there is a result available so we can assign text and run the rest of the method.

It's just like in my analogy. Someone asks you for a document. You send away in the mail for the document and keep on doing other work. When it arrives in the mail you are signalled, and when you feel like it, you do the rest of the workflow -- open the envelope, pay the delivery fees, whatever. You don't need to hire another worker to do all that for you.

Answered by: Eric Lippert on StackOverflow

Code sample :

class Program
{
    static void Main(string[] args)
    {
        using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
        {
            Console.CancelKeyPress += (s, e) =>
            {
               e.Cancel = true;
               Console.WriteLine("Stopped by user");
               cancellationTokenSource.Cancel(true);
            };
            try
            {
               MainAsync(cancellationTokenSource).GetAwaiter().GetResult();
            }
            catch (OperationCanceledException) 
            {
               Console.WriteLine("Operation has been cancelled by the user.");
               Console.ReadLine();
            }
         }
     }}
     private static async Task MainAsync(CancellationTokenSource cancellationTokenSource)
     {
         Console.WriteLine("Exercise 1 :");
         var tasks = new List<Task>();
         var resourceList = new string[] { "resourceA", "resourceB", "resourceC" };

         IEnumerable<Task<string>> getLengthTask =
                from resorce in resourceList
                select GetResourceContentAsync(resorce, cancellationTokenSource.Token);
         
         Console.WriteLine("Press CTRL+C at anytime to Cancel");
         Console.WriteLine("Getting data from remote server...");
            
         var content = await Task.WhenAll(getLengthTask.ToArray());

         Console.WriteLine($"Total Content Length : {content.ToList().Sum(c => c.Length)}");
         Console.ReadLine();

     }

     private static async Task<string> GetResourceContentAsync(string resourceId, CancellationToken token)
     {
          HttpClient client = new HttpClient();
          Console.WriteLine($"Value has been requested from '{resourceId}'");
          var responseMessage = await client.GetAsync($"https://localhost:44345/api/{resourceId}", token);
          Console.WriteLine($"Response has been received from '{resourceId}'");
          return await responseMessage.Content.ReadAsStringAsync();
      }