Count Working Days

Tested on:
.Net Framework 4.8

Calculate working days (Monday, Tuesday, Wednesday, Thursday and Friday) given 2 dates.

For example:
– Monday 8/2/2021 to Wednesday 8/4/2021 is 2 days – In this case, 8/4/2021 is excluded because the time is not specified and in .Net it automatically assigned to 12:00 AM.
– Monday 8/2/2021 12 PM to Wednesday 8/4/2021 12 PM is 2 days.
– Friday 8/6/2021 12 PM to Tuesday 8/10/2021 6 PM is 2.25 days.

public static double GetWorkingDays(DateTime startDate, DateTime endDate)
{
    // Get next full day from start date and last full day of end date
    var nextFullStartDate = startDate.AddDays(1).Date;
    var lastFullEndDate = endDate.Date;

    // Calculate total days based on start and end's day of week
    var dayOfWeekFactor = (nextFullStartDate.DayOfWeek - lastFullEndDate.DayOfWeek) * 2;
    if (lastFullEndDate.DayOfWeek == DayOfWeek.Sunday)
    {
        // In .net, day of week for Sunday is 0, we need to change it to 7
        dayOfWeekFactor = ((int)nextFullStartDate.DayOfWeek - 7) * 2;
    }

    // Calculate working days (ie: Monday, Tuesday, Wednesday, Thursday and Friday)
    var workingDayCount = ((lastFullEndDate - nextFullStartDate).TotalDays * 5 - dayOfWeekFactor) / 7;

    // Subtract working days if full start date or last full end date is Sunday
    // Saturday is not included here because if startDate is Saturday the formula above would have excluded Saturday. If the endDate is Saturday, it would have been excluded too because the time would be Saturday 12:00 AM
    if (nextFullStartDate.DayOfWeek == DayOfWeek.Sunday || lastFullEndDate.DayOfWeek == DayOfWeek.Sunday)
    {
        workingDayCount--;
    }

    // Count the real start/end date
    if (startDate.DayOfWeek != DayOfWeek.Saturday &&
        startDate.DayOfWeek != DayOfWeek.Sunday)
    {
        var startDateFraction = (nextFullStartDate - startDate).TotalHours / 24;
        workingDayCount += startDateFraction;
    }

    if (endDate.DayOfWeek != DayOfWeek.Saturday &&
        endDate.DayOfWeek != DayOfWeek.Sunday)
    {
        var endDateFraction = (endDate - lastFullEndDate).TotalHours / 24;
        workingDayCount += endDateFraction;
    }

    return workingDayCount;
}

References:
Stackoverflow

New Year Reading List

An Introduction to DataFrame

The cool in-memory schema-on-read DataFrame that is widely used in Python and other machine learning platform (Apache Spark, Databricks, etc) is coming to .NET. It does remind me of `DataSet` and `DataReader`.


Memory-wise apps with C# .NET

Very nice post by Ali, compiling from different sources and lay out how to write memory-efficient C# app.

20 Predictions about Software Development trends in 2020

An interesting perspective about what’s coming in 2020. From a quick glance, it looks like reasonable predictions.


Top 7 Modern programming languages to learn now

Rust is on the top, followed by Go. Two modern language which popularity has been gaining a lot of momentum lately. This post explains the basic of modern programming language and benefits of languages like Rust and Go.


Atomic Design Methodology

Online book by Brad Frost to explain the concept of atomic design. It’s a concept that mimic biological molecules and construct UI elements in a modular way for re-usability and maintainability.


Unit Test Entity Framework

Tested with:
.Net Framework 4.5
Entity Framework 6.2.0
Moq 4.13.1
MSTest 1.3.2

Github repository here.

This is a demo of how to write unit tests for Entity Framework.
This demo is based on Microsoft article.
It consists of testing EF query and non-query scenarios on both async and non-async calls.

The entity model looks like this.

2019-12-23 14_20_09-Infinity - Microsoft Visual Studio

The data access class look like this.

public class InfinityDataAccess
{
    private readonly InfinityEntities dbContext;
    public InfinityDataAccess(InfinityEntities dbContext)
    {
        this.dbContext = dbContext;
    }

    public IEnumerable<Misc> GetMisc()
    {
        using (this.dbContext)
        {
            return this.dbContext.Misc
                .Select(o => o)
                .ToList();
        }
    }

    public async Task<IEnumerable<Misc>> GetMiscAsync()
    {
        using (this.dbContext)
        {
            return await this.dbContext.Misc
                .Select(o => o)
                .ToListAsync();
        }
    }

    public bool InsertMisc(string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var newModel = new Misc
                {
                    Data = data,
                    Description = description
                };

                this.dbContext.Misc.Add(newModel);
                this.dbContext.SaveChanges();
                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public async Task<bool> InsertMiscAsync(string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var newModel = new Misc
                {
                    Data = data,
                    Description = description
                };

                this.dbContext.Misc.Add(newModel);
                await this.dbContext.SaveChangesAsync();
                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public bool UpdateMisc(int miscId, string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = this.dbContext.Misc.Find(miscId);

                if (dataModel != null)
                {
                    dataModel.Data = data;
                    dataModel.Description = description;
                    this.dbContext.SaveChanges();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public async Task<bool> UpdateMiscAsync(int miscId, string data, string description)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = await this.dbContext.Misc.FindAsync(miscId);

                if (dataModel != null)
                {
                    dataModel.Data = data;
                    dataModel.Description = description;
                    await this.dbContext.SaveChangesAsync();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public bool DeleteMisc(int miscId)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = this.dbContext.Misc.Find(miscId);

                if (dataModel != null)
                {
                    this.dbContext.Misc.Remove(dataModel);
                    this.dbContext.SaveChanges();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public async Task<bool> DeleteMiscAsync(int miscId)
    {
        try
        {
            using (this.dbContext)
            {
                var dataModel = await this.dbContext.Misc.FindAsync(miscId);

                if (dataModel != null)
                {
                    this.dbContext.Misc.Remove(dataModel);
                    await this.dbContext.SaveChangesAsync();
                }

                return true;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }
}

For query scenario on non-async call, it is pretty straight forward.

[TestMethod]
public void TestGetMisc()
{
    // Data to be returned
    var data = new List();
    data.Add(new Misc { Data = "Data1", Description = "Description1" });
    data.Add(new Misc { Data = "Data2", Description = "Description2" });
    data.Add(new Misc { Data = "Data3", Description = "Description3" });

    // Create mock data
    var mockData = new Mock();
    mockData.As().Setup(m => m.Provider).Returns(data.AsQueryable().Provider);
    mockData.As().Setup(m => m.Expression).Returns(data.AsQueryable().Expression);
    mockData.As().Setup(m => m.ElementType).Returns(data.AsQueryable().ElementType);
    mockData.As().Setup(m => m.GetEnumerator()).Returns(data.AsQueryable().GetEnumerator());

    // Create mock EF context
    var mockContext = new Mock();
    mockContext
        .Setup(mock => mock.Misc)
        .Returns(mockData.Object);

    // Assert
    var dataAccess = new InfinityDataAccess(mockContext.Object);
    var result = dataAccess.GetMisc();
    Assert.IsNotNull(result);
    Assert.AreEqual(3, result.Count());
    Assert.AreEqual("Description1", result.FirstOrDefault(o => o.Data == "Data1").Description);
}

The test for query scenario creates mock data of queried EF entity model and setup the mock’s Provider, Expression, ElementType and Enumerator. The return object of the setup are the correspondent properties of the returned data which is a type of IQueryable (see // Create mock data in the code above).
Next, the test creates mock of EF context. The mock is setup to return mock data we created earlier (see // Create mock EF context in the code above).

For non-query scenario on non-async call, it is almost similar to query scenario.

[TestMethod]
public void TestInsertMisc()
{
    // Data to be returned
    var data = new Mock();

    // Create mock EF context
    var mockContext = new Mock();
    mockContext
        .Setup(mock => mock.Misc)
        .Returns(data.Object);

    // Assert
    var dataAccess = new InfinityDataAccess(mockContext.Object);
    var result = dataAccess.InsertMisc("UnitTestData1", "UnitTestDescription1");
    Assert.IsTrue(result);
    mockContext.Verify(m => m.Misc.Add(It.IsAny()), Times.Once);
    mockContext.Verify(m => m.SaveChanges(), Times.Once);
}

The test creates mock data of EF entity model, but it is not necessary to setup the mock’s Provider, Expression, ElementType or Enumerator.
Next, the test creates mock of EF context (see // Create mock EF context in the code above).

For async calls, there are additional helper classes we need to create.
These classes are in-memory query provider to process async requests. We use custom query provider because EF use LINQ extension methods for async calls and these methods are designed to be used only with EF. If we try to use them with our unit tests, it will throw errors.
The 3 classes we need to create are:

  1. DbAsyncQueryProvider
  2. DbAsyncEnumerable
  3. DbAsyncEnumerator

With these helper classes, we can create mock data capable of in-memory async calls. This is the generic method to create the mock data.

private Mock GenerateMockDbSet(IQueryable mockData)
    where T : class
{
    var mock = new Mock();
    mock.As()
        .Setup(x => x.GetAsyncEnumerator())
        .Returns(new TestDbAsyncEnumerator(mockData.GetEnumerator()));

    mock.As()
        .Setup(x => x.Provider)
        .Returns(new TestDbAsyncQueryProvider(mockData.Provider));

    mock.As()
        .Setup(x => x.Expression)
        .Returns(mockData.Expression);

    mock.As()
        .Setup(x => x.ElementType)
        .Returns(mockData.ElementType);

    mock.As()
        .Setup(x => x.ElementType)
        .Returns(mockData.ElementType);

    return mock;
}

So for query scenario on async call, we just call the above method to create mock data for us.

[TestMethod]
public async Task TestGetMiscAsync()
{
    // Data to be returned
    var data = new List();
    data.Add(new Misc { Data = "Data1", Description = "Description1" });
    data.Add(new Misc { Data = "Data2", Description = "Description2" });
    data.Add(new Misc { Data = "Data3", Description = "Description3" });

    // Create mock data
    var mockData = GenerateMockDbSet(data.AsQueryable());

    // Create mock EF context
    var mockContext = new Mock();
    mockContext
        .Setup(mock => mock.Misc)
        .Returns(mockData.Object);

    // Assert
    var dataAccess = new InfinityDataAccess(mockContext.Object);
    var result = await dataAccess.GetMiscAsync();
    Assert.IsNotNull(result);
    Assert.AreEqual(3, result.Count());
    Assert.AreEqual("Description1", result.FirstOrDefault(o => o.Data == "Data1").Description);
}

There are more sample tests on the github repository to demonstrate every single scenarios in both async and non-async calls.

More Reading List

100 new requests in Node.js while still serving the first one

This is an interesting look into how Node.js works under the hood when serving multiple requests. It’s different than how Apache, Tomcat or IIS serve the request from users. Pretty interesting.


Promises and async/await relationship

I always wonder how they actually relate to each other. This short post explains it concisely. They are also interchangeable.


Best Practices for REST API Error Handling

I’d categorize this more of “basic” practices. However, just because it’s basic, doesn’t mean you can ignore them. In fact, they are very important in building APIs.


How to handle exceptions in asynchronous code in C#

The main (and probably the only) takeaway from this post is that exception thrown in an `async` method that returns a `Task` object is wrapped in an instance of `AggregateExpcetion` which you would have to access with `tasks.Exception` instance. Check out the code example in the post.


Reduce Change Detection Cycles with Event Coalescing in Angular

Event bubbling in Angular app can be problematic when it triggers change detection. This post shows you how to coalesce them.


Machine Learning / AI Reading List

Common Errors in Machine Learning due to Poor Statistics Knowledge

You can learn by doing, or you can learn from someone else’s mistakes. This is the case of the later. Certainly useful to avoid the same mistakes.


Continuous Delivery for Machine Learning

This one is pretty heavy read. But if you’re into Martin Fowler’s stuff, you know they are ‘the standard’. This one covers what it takes to apply continuous delivery in machine learning model. The CD for machine learning have similarities to software’s CD, but there are few keys differences as well.


Introduction to Machine Learning in C# with ML.NET

If you want to start learning Machine Learning but don’t know where to start, ML.NET is a good starter. With familiarity of C# and .NET, you could pick up ML.NET fairly quickly. This goes into details on how to get started with ML.NET, even covers Auto-ML!


Identify guiding principles for responsible AI in your business

Everyone thinks AI is cool, futuristic and can solve _almost_ all the problems. But not many think about the consequences, side effects and what it would take to build it right. In another word, a responsible AI. This mini-course go over what we need to consider in building AI.


Multiprocessing vs. Threading in Python: What Every Data Scientist Needs to Know

I like how Sumit gives intro to parallel computing, specifically multi processes vs threading, before he went dive into how it’s applicable in Python for modeling. Worth read even if you skip the Python part.


Programmatically Configure EF DbConfiguration

Tested on:
Entity Framework 6.2.0

There are few ways to set EF configuration, this describes using code-based DbConfiguration.

  1. Create a class inherit from DbConfiguration.
    using System.Data.Entity;
    
    namespace InfinityDataModel
    {
        public class InfinityConfiguration : DbConfiguration
        {
            public InfinityConfiguration()
            {
                // Sample configuration
                SetDefaultConnectionFactory(new LocalDbConnectionFactory("InfinityDb"));
            }
        }
    }
    

  2. The class must be in same assembly as your the Entity Framework Data Model.

  3. In the constructor, set the configuration you wanted. For all possible configurations, see here.
  4. There is no need to do anything else. EF will load your configuration class when initialized.

References:
Microsoft

What to Read this Week?

Integrating Cosmos DB with OData (Part 1)

Azure Cosmos DB is great, but what if you need expose it as OData standard, including the query in URI convention? Well, you integrate it with OData. Hassan covers the basic of Cosmos DB, what is it and how to set it up, and how to integrate it with OData.

40 Visual Studio Code Plugins I Have

One can never has enough Visual Studio Code plugins. Here’s another 40 for you.

Open Neural Network Exchange (ONNX)

Machine learning is on the rise and everyone develops their own standard. ONNX (read `onix`) is an open standard model for machine learning. This explains what is it in more details as well as where to get the pre-build ONNX models (model zoo).

Introduction to Big O Notation and Time Complexity (Data Structures & Algorithms #7)

CSDojo explains Big O Notation in a simple, easy to understand way and how time and space complexity are calculated. There are some maths involved, but they are pretty basic.

C# Data Structures

And along with Big O Notation, these articles go over the data structures that are available in C#. Learning and knowing when to use these data structures are important in building the fast algorithm.

What I’m Reading This Week.

“Maybe” monad through async/await in C# (No Tasks!)

https://habr.com/en/post/458692/

Dmitry Tikhonov outlines how to create `Maybe` object in C# that carries 2 states (think about success and failure object) in a monad way. The implementation includes code sample and usage in async / await.

 

Functional Programming In Object-Oriented Programming In C#

https://www.codeproject.com/Articles/5162828/Functional-Programming-in-Object-Oriented-Programm

Emulate functional programming in an object oriented programming world. Yes it is possible. I do feel a basic understanding of functional programming is needed.

 

2019 State of Testing Report

https://www.infoq.com/articles/2019-state-testing-report/

Worth your time to read if you are involved a lot in testing. At least, read the “Key Takeaways”. This report covers what’s going on around global testing community as it surveys 1000 participants from around 80 countries.

 

Clancey’s HotUI

https://github.com/Clancey/HotUI

A MVU (Model View Update) way of building UI. Platform supported includes: iOS, Android, UWP, WPF, Mac OS, Xamarin.Forms, Blazor. And it support hot reload! It’s still proof of concept though, definitely don’t use it in production.

 

Jason Livesay’s NoScriptWeb

https://github.com/runvnc/noscriptweb

I thought this is a very cool concept. The idea is to build all pages in a website from markdown. 100% JavaScript free. That means, no ads, secure, fast browsing. Still work in progress, but promising.

C# Check if PropertyType is Null

You want to check if a property’s PropertyType is nullable. In the example below, only property `IsStudent` is nullable.

User.cs

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool? IsStudent { get; set; }
}

Checking if PropertyType is nullable is useable when adding column to `DataTable` object. If column to be added is nullable type, we need to explicitly set it.

To check if PropertyType is nullable, we can use `System.Nullable.GetUnderlyingType(Type nullableType)`, see example below and reference here.

public void GetUsers()
{
    System.Reflection.PropertyInfo[] properties = typeof(User).GetProperties();
    System.Reflection.PropertyInfo[] readableProperties = properties.Where(w => w.CanRead).ToArray();
    foreach (var property in readableProperties)
    {
        var propertyType = property.PropertyType;
        if (System.Nullable.GetUnderlyingType(propertyType) != null)
        {
            // It's a nullable type
        }
        else
        {
            // It's not a nullable type
        }
    }
}

Reference
Stackoverflow

DynamicProxyGenAssembly2

DynamicProxyGenAssembly2 is a temporary assembly built by mocking systems that use CastleProxy like Moq or NSubsitute. It is generated when the mock is needed and disposed of after the tests are finished.

Tested on:
Moq 4.10 https://github.com/moq/moq4
.Net 4.5

Following is AssemblyInfo.cs in QC.Client project.

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("QC.Client")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QC.Client")]
[assembly: AssemblyCopyright("Copyright ©  2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

[assembly: Guid("d62d1a60-782a-46d8-b5f5-2f6d12ad1339")]

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("QC.ClientTest")]

Following is class i want to test.
UserManagement.cs (In QC.Client project)

namespace QC.Client
{
    public class UserManagement
    {
        public void UpdateUser(string address)
        {
            var executer = new Executer();
            executer.Run();
        }
    }
}

Executer.cs (In QC.Client project)

namespace QC.Client
{
    public class Executer
    {
        internal virtual bool Run()
        {
            return true;
        }
    }
}

Following is my unit test.
UserManagementTest.cs (In QC.ClientTest project)

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using QC.Client;

namespace QC.ClientTest
{
    [TestClass]
    public class UserManagementTest
    {
        [TestMethod]
        public void UpdateUserShouldWork()
        {
            // Mock
            var mock = new Mock();
            mock.Setup(x => x.Run());

            // Act
            var userManagement = new UserManagement();
            userManagement.UpdateUser("Test Address");

            // Assert
            mock.Verify(x => x.Run(), Times.Once);
        }
    }
}

Problem
MS Test throwing following error when unit testing internal member of a class in different project.
When unit test in above `UserManagementTest.cs` is run, MS Test throw following error:

Message: Test method QC.ClientTest.UserManagementTest.UpdateUserShouldWork threw exception:
System.ArgumentException: Cannot set up Executer.Run because it is not accessible to the proxy generator used by Moq:
Can not create proxy for method Boolean Run() because it or its declaring type is not accessible. Make it public, or internal and mark your assembly with [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] attribute, because assembly QC.Client is not strong-named.

Note:
– MS Test only throw exception if the accessor of method being tested is internal. In above example it is `Executer.Run()`.
– Virtual keyword in method being tested is to allow Moq to mock the method.

Solution is to simply add following code in AssemblyInfo.cs

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

Sources
Stackoverflow