Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Sunday, June 7, 2020

Weather App With Google Maps Demo Using Blazor Server, HttpClient and Radzen Components

My favorite teacher for C# on Youtube is Tim Corey, and his latest material concerns HttpClient, using a Weather Forecast Api.
See his material, and check the code provided, as this is a the beginning step towards our application. My application is live: https://httpclientwithmaps.azurewebsites.net
Final project is: https://github.com/zoltanhalasz/HttpClientWithMaps The way the final application works:
1. map is centered in Central Europe
2. click on the map- we will see the neighboring cities with available weather data
3. click on a red bullet - (marker) - the available weather forecast will be displayed in the table on the right.

Prerequisites:
1. Dotnet Blazor Server Side Basics - see my previous tutorial
2. Check Radzen Controls for Maps - check the source
https://blazor.radzen.com/googlemap
3. Check the Weather Api - it's the same source as mentioned by Tim
https://www.metaweather.com/api/
Steps to follow:
A. Take the sample application as starting point from Tim (it's a Blazor Server Application)
B. Add Blazor Radzen to the project, as presented below:
https://blazor.radzen.com/get-started
C. Add the following Changes, described below:

1. Add another class to Model folder to track the locations (which will be represented as red dots on the map)
    public class LocationModel
    {
        public int distance { get; set; }      
        public string title { get; set; }
        public string location_type { get; set; }
        public int woeid { get; set; }
        public string latt_long { get; set; }
        public double latt { get; set; }
        public double _long { get; set; }
    }

2. The code is commented, to understand the main functions, you can copy the WeatherData.razor page content into your project. This contains the functionality described in the beginning.

Please check the map functionality and weather api in the prerequisites to understand it.

3. The left menu is slightly simplified versus the Tim version, you can copy or leave it.

Enjoy! Let me know your comments.

Tuesday, January 21, 2020

Missing Pieces in My Learning for 2020

If you read my posts here, it can be seen that my main technology used is Microsoft's .Net with C#.
My main apps are WPF, with Dapper ORM/SQL, and a small module in Asp.Net core Razor pages. But I still feel I have many missing parts in my learning process. I am finding the following tutorials really interesting to pursue, and cover these areas. I started them, but didn't go through them in detail. I am glad I found these, and this is the plan for me during the first half of 2020.



A. Identity Framework for Asp.Net Core.
I did some small tutorials this far on this topic, and lately I found this one. Code Maze is the best at C# tutorials, and this is my next one on Identity:
https://code-maze.com/identity-asp-net-core-project/
I feel there are missing pieces for me in this framework, and please let me have new materials if you find some.

B. Entity Framework Core
I used EF Core in my Asp.Net web project, but I still think that there are things to be learnt here. I found Tim's newest tutorial on this, quickly checked it but didn't have time to go deeply... Another one to check more in detail.
https://www.youtube.com/watch?v=qkJ9keBmQWo

C. Asynchronous C# with Async/Await
I started using this in my Asp and WPF project, and indeed it added some responsiveness to my apps. Need to study this deeper. Any ideas on this are welcome!

D. Logging in Asp.Net Core.
I never used this in my apps, but I plan to. The greatest source for this will be my newly purchased course on Asp.Net core 3: https://code-maze.com/ultimate-aspnet-core-3-web-api/

E. Check out Blazor, especially server side, later on, this year.

F. Some more Javascript on the front-end, and then my framework of choice, Angular. I am very behind in my learning with Angular, partly because I have to work on my projects. Currently I use some JQuery tools on my Asp.net project, like datatables.js, pivotjs, chart.js, and I really like what I discovered. Any new ideas are welcome.

Monday, January 6, 2020

Reviewing Three Asp.Net Core Tutorials


In my process of learning, in parallel to my C# projects, I am going forward with Asp.Net core, researching current practice and future trends. I came across three interesting tutorials, that combine these.

I try to be less elaborate with the review, just not to confuse the reader with too many details. Try all tutorials, and provide your feedback about them! I am a fan of learning from multiple sources, gradually, increasing complexity and depth step by step.



A. https://codinginfinite.com/creating-admin-panel-asp-net-core-mvc-tutorial/#choosing-template

This one, is aiming to build a nice admin LTE background, and use several practical HTML/JS tips.

The part I liked in this tutorial:
1. uses MySQL instead of MS SQL, with EF Core
2. Introduces Logging
3. Uses admin lte template, with all css/js dependencies, and uses also a custom login page
4. provides code repo on GitHub.
5. I see this tutorial as the most impactful to my activities, due to the business-like layout and approach.

What I didn't like about this tutorial:
1. Towards the end of it, it becomes superficial in explanation, hard to follow and understand
2. When I started to host the published version - somehow the admin lte is not working, and displays a mess.
3. The Role-Based Authorization part - I am not able understand this, something more detailed and systematic is needed, with better, step-by step explanations.

B.https://www.jerriepelser.com/tutorials/airport-explorer/

This aims combining Asp.Net Core Razor pages with lots of javascript APIs from the internet, especially those focused on maps and geolocation. I find this tutorial very high quality and easy to follow.

The pros of this tutorial:
1. Combines lots of internet APIs together with Asp.Net Core/Razor
2. Easy to follow despite its complexity
3. Very high quality explanations and step-by-step approach;
4. Provides GitHub Repo with code.

Some of the hardships:
1. Some complexity especially on the Javascript part;
2. The libraries and .net core version seem to be old;

C. https://youtu.be/8DNgdphLvag
This is Tim Corey's next tutorial, an easy introduction to Blazor Server Side. This is some very new technology and his explanations are easy to follow and shared lots of best practices.

The pros:
1. Latest technology;
2. Very easy to follow, excellent explanation;
3. Shares some nice best practices with organizing the code and database access;
4. Code provided.

The cons:
1. The example seems to be very simplistic, I would like to see a more complex application presented.(maybe a next version for him)
2. The technology presented is still not widespread. Waiting to see how Blazor proves to be in 2020 and later. Clearly Blazor Server Side is more stable, but Client side is not yet production ready.

What kind of similar tutorials would you recommend? I am especially interested in the combination of html/js/css with Razor pages (not Blazor, yet) with a focus for business applications.


Friday, December 27, 2019

Simple Excel Upload and Chosen Select Tutorial (using Asp.Net Core Razor Pages)

In any serious business tool, import and export Excel data is a basic feature. This is the fastest way to input data to the database, and Excel being so popular, it's the most common for accountants and business people to proceed like this when bulk inputting any data to an application.

Additionally, I decided to search further Jquery plugins to make my Razor Pages apps more interactive on the front-end, and that's how I found Chosen.


Prerequisites for this tutorial:
1. basic javascript/jquery
2. intermediate Razor Pages (See my other tutorials for ground knowledge)
3. website is running under: https://excelupload-chosen.zoltanhalasz.net/
4. code can be downloaded from: https://drive.google.com/open?id=10YzI-OrrhH_yN6YAKlHcJ7ZGEGZSrzP_

Materials I used to prepare this tutorial:
1. https://harvesthq.github.io/chosen/
2. inspiration for the excel upload: https://www.c-sharpcorner.com/article/using-epplus-to-import-and-export-data-in-asp-net-core/
3. I use an in-memory database for the application, see my previous Datatables 2 tutorial
4. this project is on top of my Datatables 2 tutorial, as you can see the source code, free to use.


Preliminary steps:
1. for the Razor Pages project, include latest package in Nuget manager "EPPlus"
2. Copy the css and js files for chosen in wwwroot, see source https://github.com/harvesthq/chosen/releases/

unzip the file, create a "chosen" folder in wwwroot and copy the content

3. Create a special layout page, containing the references for the css files for formatting reasons
call it "_LayoutChosen " this will be the basis for the
include these in the head tag of the layout file, just below site.css
    <link rel="stylesheet" href="~/chosen/docsupport/prism.css">
    <link rel="stylesheet" href="~/chosen/chosen.css">
4. use the following file for excel upload: https://drive.google.com/open?id=1u_zQ4JrwZ5sFXX8eX59vnXdIOPkR3wLm

Steps for the application:

1. Index page:
on the backend
- we have to populate the select list with all cost categories
- we write a function for filtering, that will be the handler for the form

    public class IndexModel : PageModel
    {
        private InvoiceContext _context;

        public List<InvoiceModel> InvoiceList;
        public IndexModel(InvoiceContext context)
        {
            _context = context;
        }

        [BindProperty]
        [Display(Name = "Category")]
        public string SelectedCategory { get; set; }

        public IList<SelectListItem> CategoryList { get; set; } = new List<SelectListItem>();

        public void OnGet()
        {
            InvoiceList = _context.InvoiceTable.ToList();
            var distinctCategories = InvoiceList.GroupBy(test => test.CostCategory).Select(grp => grp.First()).ToList();
            CategoryList.Add(new SelectListItem() { Text = "All", Value = "All" });
            foreach (var cat in distinctCategories)
            {
                CategoryList.Add(new SelectListItem() { Text = cat.CostCategory, Value = cat.CostCategory});
            }

        }

        public IActionResult OnPostFilter()
        {
            InvoiceList = _context.InvoiceTable.ToList();
            CategoryList.Add(new SelectListItem() { Text = "All", Value = "All" });
            var distinctCategories = InvoiceList.GroupBy(test => test.CostCategory).Select(grp => grp.First()).ToList();         
            foreach (var cat in distinctCategories)
            {
                CategoryList.Add(new SelectListItem() { Text = cat.CostCategory, Value = cat.CostCategory });
            }

            if (SelectedCategory == "All") SelectedCategory = "";

            InvoiceList = _context.InvoiceTable.Where(x=>x.CostCategory.ToLower().Contains(SelectedCategory.ToLower())).ToList();

            return Page();
        }

    }

on the frontend

we need to implement the form with the chosen select, and then draw the table.
below the table, we implement the chosen jquery action, as per documentation


@page
@model IndexModel
@{
    ViewData["Title"] = "Chosen";
    Layout = "_LayoutChosen";
}

    <div class="text-center">
        <h1 class="display-4">Invoice List without DataTable</h1>
        <p>
            <a asp-page="DataTableArrayRender">Show DataTable</a>
        </p>
        <p>
            <a asp-page="ExcelUpload">Upload Excel File</a>
        </p>
    </div>


<form class="col-8" id="FilterForm" method="post" asp-page-handler="Filter"> 
    <div class="form-row">
        <label asp-for="SelectedCategory" class="col-form-label col-sm-2"></label>
        <select class="chosen-select" asp-for="SelectedCategory" data-placeholder="Choose a category..."
                asp-items="@Model.CategoryList" onchange="this.form.submit()"></select>
    </div>
</form>



<table class="table table-sm">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.InvoiceList[0].InvoiceNumber)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.InvoiceList[0].Amount)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.InvoiceList[0].CostCategory)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.InvoiceList[0].Period)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.InvoiceList)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.InvoiceNumber)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Amount)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.CostCategory)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Period)
                </td>
                <td></td>
            </tr>
        }
    </tbody>
</table>

<script src="~/chosen/docsupport/jquery-3.2.1.min.js" type="text/javascript"></script>
<script src="~/chosen/chosen.jquery.js" type="text/javascript"></script>
<script src="~/chosen/docsupport/prism.js" type="text/javascript" charset="utf-8"></script>
<script src="~/chosen/docsupport/init.js" type="text/javascript" charset="utf-8"></script>

<script>
     $(".chosen-select").chosen({no_results_text: "Oops, nothing found!"});
</script>

Result as below:


2. The excel upload:
Create a new Razor Page: ExcelUpload



On the backend we will use the library from EPPlus (using OfficeOpenXml;)

We will parse the input excel file, transmitted by the form.
For the parsing, we go row by row and get the data.
The upload file has to be in the established format according to the InvoiceModel Class, else the app will throw an exception that we will treat and show an error message.

    public class ExcelUploadModel : PageModel
    {
        private IHostingEnvironment _environment;

        private InvoiceContext _context;

        public ExcelUploadModel(IHostingEnvironment environment, InvoiceContext context)
        {
            _environment = environment;
            _context = context;
        }
        [BindProperty]
        public IFormFile UploadedExcelFile { get; set; }

        [BindProperty]
        public String Message { get; set; }


        public async Task<IActionResult> OnPostAsync()
        {
                return await Import(UploadedExcelFile);
         
        }

        public async Task <IActionResult> Import(IFormFile formFile)
        {
            if (formFile == null || formFile.Length <= 0)
            {
                Message = "This is not a valid file.";
                return Page();
            }

            if (formFile.Length > 500000)
            {
                Message = "File should be less then 0.5 Mb";
                return Page();
            }

            if (!Path.GetExtension(formFile.FileName).Equals(".xlsx", StringComparison.OrdinalIgnoreCase))
            {
                Message = "Wrong file format. Should be xlsx.";
                return Page();
            }

            var newList = new List<InvoiceModel>();

            try
            {
                using (var stream = new MemoryStream())
                {
                    await formFile.CopyToAsync(stream);

                    using (var package = new ExcelPackage(stream))
                    {
                        ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
                        var rowCount = worksheet.Dimension.Rows;

                        for (int row = 2; row <= rowCount; row++)
                        {
                            newList.Add(new InvoiceModel
                            {
                                //ID = row - 1,
                                InvoiceNumber = int.Parse(worksheet.Cells[row, 1].Value.ToString().Trim()),
                                Amount = float.Parse(worksheet.Cells[row, 2].Value.ToString().Trim()),
                                CostCategory = worksheet.Cells[row, 3].Value.ToString().Trim(),
                                Period = worksheet.Cells[row, 4].Value.ToString().Trim(),
                            });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Message = "Error while parsing the file. Check the column order and format.";
                return Page();
            }


            List<InvoiceModel> oldInvoiceList = _context.InvoiceTable.ToList();
            _context.InvoiceTable.RemoveRange(oldInvoiceList);
            _context.InvoiceTable.AddRange(newList);
            _context.SaveChanges();
            //oldInvoiceList = _context.InvoiceTable.ToList();

            return RedirectToPage("./Index");
        }

    }

On the front-end



We will implement a simple upload form with an Excel file as input. Below, will be the error message in case the upload and data parsing goes wrong.
Please use the sample upload xlsx file shown in the beginning.

@page
@model DataTables.ExcelUploadModel
@{
    ViewData["Title"] = "ExcelUpload";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}

<h1>ExcelUpload</h1>

<form method="post" enctype="multipart/form-data">
    <input type="file" asp-for="UploadedExcelFile" accept=".xlsx"/>
    <input type="submit" />
</form>
<strong class="alert-danger">
    @Model.Message
</strong>

Showing the error message:

Tuesday, December 10, 2019

MongoDB CRUD with Asp.Net Core Razor Pages - Simple Tutorial




This year I had the occasion to meet the MEAN stack, M coming from the Mongo DB NoSQL database. But, during my studies with Asp.Net Core, I am thinking about a database solution for future projects, outside the MS SQL realm. Might be suitable for side projects ? Who knows, I might give a try.

This is how I met Mongo DB, and produced this tutorial, with the plan that I might want to use MongoDB with .Net in the future.

Prerequisites:
1. Basic Asp.Net Core 2.2 Razor pages knowledge, check at least the first two tutorials mentioned here: https://mydev-journey.blogspot.com/2019/11/razor-pages-not-for-shaving.html
2. Check the introductory MongoDB API tutorial from Microsoft: https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mongo-app?view=aspnetcore-2.2&tabs=visual-studio
3. My tutorial is based on point 2, just that it extends also to the front-end using Razor Pages, and then adds search function.
4. Please open an account on https://cloud.mongodb.com/ - it's free!
5. Download code from: https://drive.google.com/open?id=1FeihPX-qJz7b_zXraG32uHqoJLDTRcUr
6. Application LIVE online: http://mongotutorial.azurewebsites.net/ListBooks
7. Further study with C# from Mongo cloud provider: https://www.mongodb.com/blog/post/quick-start-csharp-and-mongodb--update-operation


A. After creating an account on the mongo cloud provider, create database on the Mongo Cloud, and a collection on the database, as below:

    "BooksCollectionName": "Books",
    "DatabaseName": "BookstoreDb"

Then, get the connection string from the Mongo Cloud, from connect application in below screen:
    "ConnectionString": "mongodb+srv://username:password@clusterxxx",


Connection string is inserted in the appsettings.json file.
B. You can replicate the tutorial on point 2 by following the material from Microsoft which I highly recommend, or simply take my zipped Repo from link.

Base class is the Book class, where I added an annotation for the Price to accept only currency values.
a. install Nuget Package: MongoDB.Driver
b. Book Class looks like:
insert
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
///
public class Book
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }

        [BsonElement("bookName")]
        public string BookName { get; set; }

        [BsonElement("price")]
        [DataType(DataType.Currency)]
        public decimal Price { get; set; }

        [BsonElement("category")]
        public string Category { get; set; }

        [BsonElement("author")]
        public string Author { get; set; }
    }



C. the main part here is the Services class which does the whole operation with the Mongo DB and collection, all CRUD operations. I added a search by title capability in my version.
insert: using MongoDB.Driver;
///
  public class BookService
    {
        private readonly IMongoCollection<Book> _books;

        public BookService(IBookstoreDatabaseSettings settings)
        {
            var client = new MongoClient(settings.ConnectionString);
            var database = client.GetDatabase(settings.DatabaseName);

            _books = database.GetCollection<Book>(settings.BooksCollectionName);
        }

        public List<Book> Get() =>
            _books.Find(book => true).ToList();

        public List<Book> FindByTitle(string title) =>
            _books.Find(book => book.BookName.ToLower().Contains(title.ToLower())).ToList();

        public Book Get(string id) =>
            _books.Find<Book>(book => book.Id == id).FirstOrDefault();

        public Book Create(Book book)
        {
            _books.InsertOne(book);
            return book;
        }

        public void Update(string id, Book bookIn) =>
            _books.ReplaceOne(book => book.Id == id, bookIn);

        public void Remove(Book bookIn) =>
            _books.DeleteOne(book => book.Id == bookIn.Id);

        public void Remove(string id) =>
            _books.DeleteOne(book => book.Id == id);
    }


D. My tutorial adds Razor pages to the project, which can display data, and do all the CRUD via separate pages. The Razor pages are scaffolded using a fake entity framework context, just to make the coding faster.

Basically, the CRUD Razor pages were scaffolded to Edit, Create, Delete or List all elements from the Mongo Table. Please follow the code to see the details.

E. In order to demonstrate the search capabilities of MongoDB, I added a form to search by book title,
The result of the application should look like below:

Friday, November 29, 2019

The Tutorials With Most Impact in 2019

After relating about tutorial hell in my previous posts, I wanted to present a short list with the most important tutorials of 2019, that impacted my developer life significantly. In total, I might have done maybe a hundred tutorials in this transition year, but some of them were so far - reaching, that they are the backbone of my current projects.


1. introduction to Dapper ORMhttps://www.youtube.com/watch?v=Et2khGnrIqc
additional materials were:
Advanced Dapper: https://www.youtube.com/watch?v=eKkh5Xm0OlU&t=3s
Stored Procedures: https://www.youtube.com/watch?v=Sggdhot-MoM
LINQ: https://www.youtube.com/watch?v=yClSNQdVD7g

2. Asp.Net Core - the basics
a. general introduction with MVC: https://code-maze.com/asp-net-core-mvc-series/
b. Entity Framework Core: https://code-maze.com/entity-framework-core-series/
c. Microsoft Razor Pages Tutorial: https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-2.2&tabs=visual-studio
d. A bit more advanced tutorial for Razor Pages: https://www.learnrazorpages.com/razor-pages/tutorial/bakery

3. Angular/Material Design/Firebase
https://angular-templates.io/tutorials/about/angular-crud-with-firebase

My applications in 2019 are very much dependent on the ideas and technologies mentioned in these tutorials. Of course, I studied additional techniques and ideas to fulfill my work, but these were the most interesting and impactful ones for me in 2019.

What are your main tutorials for 2019 or recent years?

Bulk Insert With Dapper - The Right One

One of my favorite online trainers, Tim Corey, introduced Dapper for me two years ago. It was only the last week when I stumbled upon his advanced Dapper video, and implemented the correct version for a bulk insert, using this micro-ORM.

Prerequisites:
- install Dapper nuget package;
- intermediate C#/with MS SQL database;

The task of our bulk insert will be to insert the following data into an MS SQL database:

a. Table structure in SQL, defined by the query:

CREATE TABLE [dbo].[InvoiceSummary](
[id] [int] IDENTITY(1,1) NOT NULL,
[Inv_Number] [int] NOT NULL,
[IssueDate] [datetime] NOT NULL,
[BillingCode] [nvarchar](100) NOT NULL,
[EntityName] [nvarchar](200) NOT NULL,
[BUName] [nvarchar](100) NOT NULL,
[Value] [float] NOT NULL,
[VAT] [float] NOT NULL,
[TotalValue] [float] NOT NULL,
[Currency] [nvarchar](50) NOT NULL,
[ExchangeRate] [float] NOT NULL,
[Entity_Id] [int] NOT NULL,
[BU_id] [int] NOT NULL,
[UpdatedBy] [nvarchar](100) NOT NULL,
[UpdatedAt] [datetime] NOT NULL,
[PeriodID] [nvarchar](50) NOT NULL,
[Comments] [nvarchar](200) NOT NULL,
[Comment] [nvarchar](200) NOT NULL,
[Status] [nvarchar](50) NOT NULL,
[AttentionOf] [nvarchar](300) NOT NULL,
[CC] [nvarchar](300) NULL,
[HFMCode] [nvarchar](100) NULL,
 CONSTRAINT [PK_InvoiceSummary] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[InvoiceSummary] ADD  CONSTRAINT [DF_InvoiceSummary_UpdatedAt]  DEFAULT (getdate()) FOR [UpdatedAt]
GO

b. There is a type defined, for the table-valued parameter, see SQL statement below:

CREATE TYPE [dbo].[BasicUDT] AS TABLE(
[id] [int] NOT NULL,
[Inv_Number] [int] NOT NULL,
[IssueDate] [datetime] NOT NULL,
[BillingCode] [nvarchar](100) NOT NULL,
[Entity_Id] [int] NOT NULL,
[BU_id] [int] NOT NULL,
[EntityName] [nvarchar](200) NOT NULL,
[BUName] [nvarchar](100) NOT NULL,
[Value] [float] NOT NULL,
[VAT] [float] NOT NULL,
[TotalValue] [float] NOT NULL,
[Currency] [nvarchar](50) NOT NULL,
[ExchangeRate] [float] NOT NULL,
[Comments] [nvarchar](200) NOT NULL,
[AttentionOf] [nvarchar](300) NOT NULL,
[CC] [nvarchar](300) NULL,
[HFMCode] [nvarchar](100) NULL,
[UpdatedBy] [nvarchar](100) NOT NULL,
[UpdatedAt] [datetime] NOT NULL,
[PeriodID] [nvarchar](50) NOT NULL,
[Comment] [nvarchar](200) NOT NULL,
[Status] [nvarchar](50) NOT NULL
)
GO

c. Stored procedure, to insert into our table, using table valued parameter:

CREATE procedure [dbo].[spInvoiceSummaryInsertSet]
@invsummary BasicUDT readonly
as
begin
set nocount on;
INSERT INTO [dbo].[InvoiceSummary]
           ([Inv_Number]
           ,[IssueDate]
           ,[BillingCode]
           ,[Value]
           ,[VAT]
           ,[TotalValue]
           ,[Currency]
           ,[ExchangeRate] 
           ,[Entity_Id]
           ,[BU_id]           
           ,[UpdatedBy], UpdatedAt
           ,[PeriodID]
           ,[Comment]
           ,[Status],
    [Comments]           
           ,[AttentionOf]
           ,[CC]
           ,[HFMCode],
   [EntityName],
   [BUName]
   )
SELECT [Inv_Number]
           ,[IssueDate]
           ,[BillingCode]
           ,[Value]
           ,[VAT]
           ,[TotalValue]
           ,[Currency]
           ,[ExchangeRate] 
           ,[Entity_Id]
           ,[BU_id]           
           ,[UpdatedBy], CURRENT_TIMESTAMP
           ,[PeriodID]
           ,[Comment]
           ,[Status],
    [Comments]           
           ,[AttentionOf]
           ,[CC]
           ,[HFMCode],
   [EntityName],
   [BUName]
from @invsummary


end;

d. Our original list in C# will contain the values we need to insert into the table:

// myInvList is a list of InvoiceSummary items defined by the class above at a)
InvoiceSummaryInsertSet(myInvList)

e. Our list is getting inserted into SQL Server DB using the table valued parameter

        public void InvoiceSummaryInsertSet(List<InvoiceSummary> myInvList)        {

            var dt = new ExcelServices().ConvertToDataTable(myInvList);

            using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(connectionString))
            {
                var p = new
                {
                    invsummary = dt.AsTableValuedParameter("BasicUDT")
                };

                connection.Execute("dbo.spInvoiceSummaryInsertSet ", p, commandType: CommandType.StoredProcedure);
            }
        }

f. helper function to transform a list into datatable, used above, is implemented as below:

        public System.Data.DataTable ConvertToDataTable<T>(IList<T> data)

        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));

            System.Data.DataTable table = new System.Data.DataTable();

            foreach (PropertyDescriptor prop in properties)
            {
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            }

            foreach (T item in data)

            {

                DataRow row = table.NewRow();

                foreach (PropertyDescriptor prop in properties)
                {
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;             

                }

                table.Rows.Add(row);
            }

            return table;

        }

That's all, it works ! Hopefully it helped some of you.

Thursday, November 28, 2019

The Challenges of Writing Business Apps/Tools


As mentioned in my previous posts on this blog, my developer journey began as an intersection between the corporate world (accounting) and programming. I used to support my own accounting processes and help others with various VBA/Excel, Access, SQL tools and that's how the journey began.

Outgrowing my role as a Management Accountant in this technological sense, in 2019 I began studying and writing full time additional applications for business/accounting problems.

The basic idea of the tools is automating Excel-based processes in a more coherent database-app approach. There are a lot of struggles in my journey, but and I have learnt a lot, especially .Net technologies and SQL, and in the meantime, the web-stack using JavaScript and lately ASP.NET Core/Razor pages.


Clearly, the biggest challenge in all these is the mapping of real world processes (based on Excel and manual work) to an application. What's needed for this to be successful? In no particular order, my conclusions are:
1. very good understanding of the processes. This takes time and lots of communication/questions.
2. Understanding inputs and outputs. Data structure, types, formats, steps, validation, internal checks of the applications, stages of completion, reports, application logic and flow all come from inputs and outputs.
3. Thinking about the entity/DB structure and program flow.
4. From the mental mapping above come the DB structure, and then flow. Usually the flow is the succession of operations: input data, review data, edit, delete, search, etc, add more data, filter, prepare intermediary reports and then further add data, filter, edit if needed and then generate final outcome (reports, files). This cycle above can have multiple stages and checks/reports built within.
5. Validate the proposed process with the customer.
4. Discussing old methods vs new optimized process: lessons learned and areas to improve on in the new system based on feedback.

My big projects in the last 2 years are:
1.  Manufacturing Reporting/Statistics tool in MS ACCESS, on key phases of the production line. (manufacturing shop floor).
2.  Internal recharge system of the company, for distribution of indirect/administrative costs. Technology: C#, .Net, WPF/MVVM and SQL Server
3. My current project is an invoicing software that collects and invoices costs by employees. Using same technology as above. + Asp.net Core Razor pages
4. Another project for 2020 will be a VAT reporting tool to automate an Excel-based approach inside the accounting department, consolidating, filtering, automating data collection from several internal business units (big departments), and preparing statutory reports for Value Added Tax.

Some clear lessons to change the Excel-Based approach into a more efficient application are:
1. Using one database instead of many files, on a central server/Azure, for each app.
2. Mapping the entities from the excel files => as database tables/ and POCO entities.
3. All the automation of the repetitive processes go to C# code = > helper, data manipulation functions, using LINQ with lists etc.
4. Report generation, using ReportViewer tool, or ClosedXML to export excel files upon request;
5. Code re-usability.

Some architectural conclusions of the journey are:
1. need to manage the users of the application
2. implementing a reporting system, with parametrised queries, using SQL/Dapper/Reportviewer and/or simple Excel reports
3. implementing a concept of "Period": the accounting month in which all transactions take place. Afterwards the period is closed, and next month is opened for another series of transactions.
4. Implementing different types of Tables / entities by functionality:
  • tables with reduced number of updates such as business units, customers, users
  • tables with some  more frequent updates (such as employees, price lists)
  • transaction tables (allocation keys calculated, monthly cost information, monthly invoice details, etc)
5. For transaction tables, insert the user and transaction date/time 
6. In some special cases, implement a history table for some entities for which the change log is important  (such as employee change history).
What do you think, what are the main points of producing such business/accounting tools? Would you do something differently from an architecture standpoint?


Tuesday, November 12, 2019

Business Logic of an Application - My Experience as Newbie Programmer

If you read my other blog posts, especially the first ones, I explain there that my background is 15 years of corporate controlling (management accounting). And 2019 was for me a transition year to - writing accounting/business software. I accumulated some SQL/C# skills in the past years, and using my business knowledge and logic, I try to build some real tools from my previous workplace's accounting department.


I can state at the beginning that having an accounting/controlling background is very useful to understand the logic of my apps. Their goal is to automatize the work of accountants, to reduce to minimum the need of using Excel files and many emails for data collection, approval etc. So, my business background proves to be helpful!

Afterwards, comes the design and programming part.


First I design the database, using an abstract model of the data that can be used in the app.

Understanding table structures and relationships in excel, and the workflow, I can build the SQL tables and relationships, keys,  indexes, queries and reports that can be integrated to the application. I do this without having a formal training on how to build business applications, just following simple logic, then some database theory, SQL knowledge, normalization, etc.

Then I design the code and start writing it.

The models of the app are representing these SQL tables and relationships, and are the foundation of the application. Example: Business Units, Employees, Expenses etc.

Then comes the application layer, with MVVM -  a viewmodel that takes care of data coming from and going to the database, manipulating user inputs, checking, validating, iterating, etc...

Then there is the View of the application - WPF - for Windows interface, which is quite simple, user screens with tabs, tables (gridview), inputs, and reports, exports, imports of data. I try to make the user interface simple and easy to navigate, with a minimal risk to do stupid things. The users are happy, because they can use a centralized database app, and thus we can eliminate a lots of emails and excel files, which are very prone to error.

As I progress with my application, I go back sometimes to redesign the database (add fields, indexes, tables), and also the code of MVVM above. This is an iterative process for me, like continuous improvement.

Last step is to populate with data, and check. This is the most time consuming part, and can feedback to  database design and coding.


What do you think? Would you do something differently? Please feel free to give me feedback on the above topics.


Thursday, November 7, 2019

Bulk Insert in Dapper into MS SQL

I am collecting costs by employee from 6 sources and then insert them into a a GeneratedDetail table. But the collected data has 1000+ rows, and the insertion one by one row is very slow. I needed to find a bulk insert solution.
SQL Server DevOps
I am using Dapper as ORM in my C# project, and MS SQL Database.
According to research, my approach would be as below. It works now quite fast, I am satisfied with the speed of execution. Feel free to comment and propose a better solution.
note: spGeneratedDetailInsert  is a stored procedure with many parameters.

        public  void GeneratedDetailInsertBulk1(List<GeneratedDetail> DetailList)
        {
            using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(connectionString))
            {
                var sql = "";           
                foreach (var mydet in DetailList)
                {               
                    sql = sql + "Exec spGeneratedDetailInsert '" + mydet.BillingCode + "', " +
                        mydet.Emp_id + ", '" +
                        mydet.Emp_name + "', " +
                        mydet.HrId + ", " +
                        mydet.Entity_id + ", " +
                        mydet.BU_id + ", '" +
                        mydet.Currency + "', '" +
                        mydet.Item + "', " +
                        mydet.ExchangeRate + ", " +
                        mydet.InitValueRON + ", " +
                        mydet.InitValueCurr + ", " +
                        mydet.MUValueCurr + ", " +
                        mydet.TotalRon + ", '" +
                        mydet.ServiceType + "', '" +
                        mydet.CostCategory + "', '" +
                        mydet.UpdatedBy + "', '" +
                        mydet.UpdatedAt + "', '" +
                        mydet.PeriodId + "' ; ";                                   
                }
                 connection.Execute(sql);
            }
        }
Note: I am not using Dapper Plus, and I don't want to.

Dapper Plus | Learn how to use Dapper Bulk Insert with ...

Wednesday, November 6, 2019

How to Calculate Estimated Time Left in C# for Time-Consuming Process



I can suggest my today's discovery for estimating the seconds left in a 3 minutes process in C#.
Anyone better approach?

            Stopwatch sw;
            long totaltime = 0; // counts the total time passed in milliseconds
            int secondsleft; // estimated time left
            int i = 0; // counter in the foreach loop
            // objList has couple of hundred elements
            //secondsleft is recalculated after each iteration

            foreach (var obj in objList)
            {
                sw = Stopwatch.StartNew();
                //some time consuming process here
                i++;
                totaltime = totaltime + sw.ElapsedMilliseconds;
                secondsleft = (int) Math.Floor((double) totaltime / i / 1000 * (objList.Count() - i));
            }

Tuesday, November 5, 2019

Programming Is The Easy Part

I was wondering lately what is the real challenge in my current project, and what is the easy part. Do I manage the challenges the right way? Can I find some optimizations?

My answer to the challenge question is yes, there is a challenge. Understanding really well customer requirements is. What is the business process behind? What are the entities and properties?
What tables to I have as an input? Fields set as a flag? Certain situations require different treatment?
How much freedom has the user, to manipulate or corrupt data?

Yes, processing the real data that goes in the application is the real challenge, mapping it to entities that can survive the changes of the life of the application.

And what to do when the input data has some flaws? Data duplication, bad codification, violation of uniqueness... how to bridge this in my database?

Writing code is the easy part.

1. there is some routinely written code: SQL queries  - 80% are repetitive, following the same pattern (not exactly same commands). Writing the entity classes and the ORM functions that map DB procedures to entities, almost totally a routine.
2. Some semi- routinely written code - linking the WPF layout with bindings to entities, setup the ViewModel and View, draw basic XAML (copy-paste, than change)... Oh how I hate this XAML.

3. The interesting part is to write some algorithmic functionality: saving files and creating emails, generating views with filtered data, writing some more complex LINQ queries, generating invoices, creating Outlook Emails, Reports with Reportviewer...

What is then the hard part?

I think understanding the requirements really well and mentally mapping out a process how to tackle the solution step by step. Visually, View by View, Tabs, Tables, Reports, and a general succession.

Then comes the execution, test, populate with data, correction, again test, again addition of data, etc.


And finally the customer feedback, and again, corrections, optimization, refactoring, test, submission to the customer.

And after several attempts, there is the prototype that can be used at least on the short term, before the next iteration.

That's my approach. What do you think, what's your process?

Lots of SQL today

As part of my big project, today I dealt with some table creation and query writing. Mentioned earlier, I use Dapper as ORM and this means no EF queries are generated automatically.
So all Insert, Update, Select etc queries have to be written manually and returned and mapped to POCO entities (simple classes) via Dapper.



I think 2 hours was spent today on this.

I created 3 big tables (10+ fields) and wrote all CRUD queries as mentioned above.

Then, using a helper class, the ORM mappings are written in one place, just to call these functions within the application, when needed.

Some demo, from Tim Corey: https://youtu.be/QVkpzuiiVtw

An the foundation, for Stored Procedures, I used this: https://youtu.be/Sggdhot-MoM

What do you think? IS EF much more efficient?

By the way, my small prototype project in .Net core Razor Pages uses EF Core, which I wanted to learn step by step to get accustomed to it. It is nice, too, I like it! For a simple web project, it is enough for my purposes.

Monday, November 4, 2019

Career transition - from Finance to Developer at age of 39

This is an interesting story. I used to be a finance professional, qualified management accountant in the local industrial zone. But, as I got into programming and deepened my knowledge, I started gaining some traction and started liking it more and more. I decided to quit the world of deadlines, stress and audits and to switch to something more creative.

The transition took approximately 12-16 month of parallel time:
- I was working full-time
- in the meantime I spent weekly 2-4 hours to study C#, SQL or work on the .NET project (internal recharge system)
- and thinking about when to make the transition.

The nice part about the learning process was:

  • already familiar with some programming, like Access DB, VBA, Excel, some php&mysql
  • familiar with tabular data and databases + SQL (I used to write some queries in my previous workplace, obtaining some data from the company ERP)
  • I always enjoyed learning, and could focus very well
The hard part:
  • the learning curve for C#, WPF, MVVM and Dapper ORM was steep. It took 6-10 months to show some results
  • I became tired after 1 year, working paralelly on the project besides my day job
  • frustration after 1 year, having seen the results, and not knowing what's the best thing to do: to quit or to do it paralelly for some time
  • became really tired at the end of 2018 by working parallel. I decided that early 2019 I need to quit and go full time into programming.

What I like about C#?

C# has been my main language of choice. I use this for my big database application, and have played with it to build some Rest API and also for Razor Pages.

It is an awesome, all-round language.


My main sources to learn it:
1. Google/stackoverflow
2. https://www.iamtimcorey.com/
3. general tutorials and questions from the internet

The nice part about the language is:
- structured, logical
- it has LINQ to manage lists - fantastic!!
- IDE from VStudio 2019 is more than helpful
- lots of tutorials/error situations on google

The less ideal part about the language is:
- linked to .NET ecosystem, you have to be lucky to find some solutions online
- could be more free tutorials tailored for beginners
- struggled to find some good live courses in the neighborhood, I needed to learn alone
- some learning curve - maybe the first year in 2017 and early 2018 (1-2 hours per week, without supervision)

What do you think about the easy and hard parts? Any ideas how to deepen my knowledge?

Sunday, November 3, 2019

Razor Pages - Not For Shaving!

This is absolutely fantastic! Easier to understand than MVC, and some additional features vs old .net Razor pages! Using Entity Framework Core.

What is Razor pages?
  • ASP.NET Core Razor Pages is a page-focused framework for building dynamic, data-driven web sites with clean separation of concerns. 
  • Razor Pages can make coding page-focused scenarios easier and more productive than using controllers and views.

Best tutorials, I did them all:
1. https://www.learnrazorpages.com/razor-pages/tutorial/bakery
2.  https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-2.2&tabs=visual-studio
3. https://kenhaggerty.com/
4. https://www.codeproject.com/Articles/1263791/ASP-NET-Core-Razor-Pages-Using-EntityFramework-Cor
5.https://www.youtube.com/watch?v=vh0UqlnM0Jw

Currently I build a small project, using EF core, which connects to an Azure database.It has aprox 15 pages, and uses a lot of Linq expressions.
Guys, did any of you have contact with this technology?
Do you have any tips?

What about .NET Core? My new target.

During September 2019, I have been awarded a second bigger project.
It is an invoicing software, which collects various costs for employees (compensation/salary, management fees, depreciation of equipment, administration cost, miscellaneous costs) and generates a recharge invoice for their respective clients. It is a Shared Service Recharge Invoicing system.

Tools used:
- WPF and MVVM with .NET (C#).
- MS SQL for database
- Dapper as ORM
- .NET Core Razor pages (.net core 2.2) for a special manager module, for manager being able to review their employees invoices 
- bootstrap as default css system for Asp.net web pages
- some jquery

For Razor pages, I needed to learn following technologies:
1. EF Core - best, and really SIMPLE, useful resource I found: https://code-maze.com/entity-framework-core-series/
2. .NET core with razor pages. Excellent resources:
I really like Razor pages, and I will write a separate blog entry for this topic, elaborating a bit more on this. Until now, I really like it, and started to progress really well during the past days.
PS: Razor Pages are now the default in the Web App category/Visual Studio!


My first big project (.NET) - and technologies used.



In the summer of 2017, together with my former finance manager, I began to design an internal recharge system for the company.
The choice was WPF for Windows (https://docs.microsoft.com/en-us/dotnet/framework/wpf/getting-started/walkthrough-my-first-wpf-desktop-application) using the old .NET, and an MS SQL Database.

We began to learn, exercise and think about the tools to use:
Our inspiration was: https://www.iamtimcorey.com/
1. IDE: Visual Studio Community 2017
2. WPF - for the visual part, front-end
3. ORM - Dapper - I think this is the best discovery ever! Tim speaks about this in his Videos.
https://www.iamtimcorey.com/blog/137806/entity-framework 

Please, check out his videos, about SQL, C# and lots of serious tutorials and courses.
 (https://stackexchange.github.io/Dapper/)
See also: https://dapper-tutorial.net/
4. MS SQL - I needed to review my SQL knowledge. Did a lot of exercises, and build many stored procedures for the application - dapper maps the entities to the data returned by those stored procedures, and I also used SP to insert and update entity data. Even if this was very time consuming in the beginning, proves to be very efficient and goal oriented.
5. lots of company data about expenses and the algorithm to create allocation keys - business logic designed together with Finance Manager.

The journey was hard. It took me probably 1 year to really get some speed, and show something to my Finance Manager colleague.

Luckily, I had my finance background, to understand the process we tried to automate, as there was a working excel macro/formula model as well used before the application.

But, I needed to fix my knowledge of C# (also using MVVM the first time for WPF) and SQL/Dapper. This meant weekly 2-3 hours of coding for 1 year to get some traction.
Main source for C# was google and Tim Corey, and my big discoveries were:
  • lists/collections of items 
  • LINQ and the foreach 
  • breaking down the tasks to smaller chunks and functions
  • writing a services class to export lists to excel using OpenXML
  • first steps in async/await

A special challenge was how to integrate the good old WinForm control ReportViewer into WPF and MVVM. I will detail these maybe in another blog post.