Saturday, September 21, 2019

Entity Framework - How to migrate when there are two database contexts in your solution

Here I will explain how to migrate when there are two separate db contexts in two separate projects in the same solution.

The format for migration commands are as follows:

enable-migrations -ContextTypeName <DbContext-Name-with-Namespaces> -MigrationsDirectory:<Migrations-Directory-Name>

DbContext-Name-with-Namespaces - This is the full path to the database context class (including namespace)

Add-Migration -configuration <DbContext-Migrations-Configuration-Class-with-Namespaces> <Migrations-Name>

DbContext-Migrations-Configuration-Class-with-Namespaces - This is the full path to the configuration class (including namespace), which was created in the previous step.

Update-Database -configuration <DbContext-Migrations-Configuration-Class-with-Namespaces> -Verbose

Example:

1) In the Nuget Package Manager Console, make sure to select the "Default Project". That is the project which the  migrations is going to happen.

2) Also if the startup project contains a App.Config, you need to add the ConnectionString 's for the two context there as well.

3) Enable migrations

PM> Enable-migrations -ContextTypeName:My.Notification.ServicesMock.Data.MyMockContext -MigrationsDirectory:MyMigrations 
Result:
Checking if the context targets an existing database...
Code First Migrations enabled for project My.Notification.ServicesMock.

Now you will see a migrations directory been created in your project as "MyMigrations", which contains the configuration class. Later on, the migrations will be added to that folder.

4) Add Migration

PM> Add-Migration -configuration My.Notification.ServicesMock.MyMigrations.Configuration "Initial"
Result:
Scaffolding migration 'Initial'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration Initial' again.

5) Update database

PM> Update-Database -configuration My.Notification.ServicesMock.MyMigrations.Configuration -verbose
Result:
Using StartUp project '...'.
Using NuGet project '...'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.

Applying explicit migrations: [61401174_Initial].
Running Seed method.

Your migrations  are complete now. Have a look in the Db.

Sunday, September 15, 2019

MOQ Framework - For test driven development

Install Moq using the Nuget package manager.

The dll will be added to you references.

Add the using directive:
using Moq;

Now you can mock your services using the Moq framework.

[Test]
public void MyClass_TestThisScenario_ShouldGetThisResult()
{

//declaration of the service in your unit test case
var mockPassengerService = new Mock<IPassengerService>();


//calling the method which I need to mock. Here it's the GetPassengers() method
mockPassengerService.Setup(a => a.GetPassengers(category,
new DateTime(2019, 08, 16, 14, 00, 00),
mappingList)).Returns(GetMultiplePassengers);

//my second moq example, here I'm sending any string value to the method to be mocked
var mockMailService = new Mock<IMailService>();
mockMailService.Setup(a => a.SendMail(It.IsAny<string>(), It.IsAny<string>()));

}

//returns the results for the mocked class
private List<Passenger> GetMultiplePassengers
{
     return new List<Passenger>()
    {
         new Passenger()
         {}
     };
}



Saturday, September 14, 2019

NUnit the ease of Setup and TearDown Attributed methods

In NUnit there are two attributes [SetUp] and [TearDown] which eases the whole process of testing many test methods. The Setup attributed method will run before each unit test is run, and the TearDown attibuted method will run after each unit test. This eases the whole process of running all the test cases at once. A Sample NUnit test fixture wuold look like this:

[TestFixture]
class BhrPassengerServiceTest
{
[SetUp]
public void Before_Each()
{
using (var context = new ApplicationDbContext())
{
context.Database.ExecuteSqlCommand("DELETE FROM TableOne");
context.Database.ExecuteSqlCommand("DELETE FROM TableTwo");
context.Database.ExecuteSqlCommand("DELETE FROM TableThree");

context.Areas.Add(AreaOne);
context.Areas.Add(AreaTwo);
context.SaveChanges();
}
TimeService.Init();
}

[TearDown]
public void Teardown()
{
}

[Test]
public void MyClassToBeTested_TestScenarioOne_ShouldGetThisResult()
                {
                }

                 private IList<string>  HelperMethodOneUsedWithInTestMethod()
                 {
                 }
         }

Saturday, September 7, 2019

How DbFunctions in Linq expression is evaluated in SQL server

var sent = _context.IsosPassengerNotifications.Any(n => n.Guid == notification.Guid &&
                                           n.DeviceRegistrationId == notification.DeviceRegistrationId &&
   DbFunctions.DiffSeconds(n.CreatedAt, TimeService.UtcNow) < 3);

when you hover over the variable in during debug time you get the SQL command for the linq query

The SQL Equivalent:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Guid] AS [Guid], 
    [Extent1].[DeviceRegistrationId] AS [DeviceRegistrationId], 
    [Extent1].[DeviceType] AS [DeviceType], 
    [Extent1].[DeviceLanguage] AS [DeviceLanguage], 
    [Extent1].[Title] AS [Title], 
    [Extent1].[CreatedAt] AS [CreatedAt], 
    FROM [dbo].[Notifications] AS [Extent1]
    WHERE (([Extent1].[Guid] = '2019-08-16/356889/977010') OR (([Extent1].[Guid] IS NULL) AND ('2019-08-16/356889/977010' IS NULL))) AND
   (([Extent1].[DeviceRegistrationId] = '01_SsH8BmeM:APA91bGdX01Uvo24qtjayPwePB3L6AWpoqTaGkG0K8SoPOAYSJa1oVzLWKcO9cXEyz8-OetoSSJQPa36upmt38U7cpy-NvfWNTDRWUab_2Vu_abtGfJGLgxIXd-Vy_YJSxvoeH_nbQuQ') OR (([Extent1].[DeviceRegistrationId] IS NULL) AND ('01_SsH8BmeM:APA91bGdX01Uvo24qtjayPwePB3L6AWpoqTaGkG0K8SoPOAYSJa1oVzLWKcO9cXEyz8-OetoSSJQPa36upmt38U7cpy-NvfWNTDRWUab_2Vu_abtGfJGLgxIXd-Vy_YJSxvoeH_nbQuQ' IS NULL))) AND
    ((DATEDIFF (second, [Extent1].[CreatedAt], '2019-09-05 10:40:28.727')) < 3)

So how does DBFunctions.DiffSeconds work. It simply converts to a DATEDIFF in SQL server.

So how does the DATEDIFF work?

DATEDIFF simply gets the second parameter and substracts it from the first parameter.
Here you might get a positive or negative value depending on the parameters passed. To examine the subtraction result you could query the database as below

SELECT DATEDIFF (second, [Extent1].[CreatedAt], '2019-09-05 10:20:28.727')
    FROM [dbo].[Notifications] AS [Extent1]
    WHERE (([Extent1].[Guid] = '2019-08-16/356889/977010') OR (([Extent1].[IsosGuid] IS NULL) AND ('2019-08-16/356889/977010' IS NULL))) AND
   (([Extent1].[DeviceRegistrationId] = '01_SsH8BmeM:APA91bGdX01Uvo24qtjayPwePB3L6AWpoqTaGkG0K8SoPOAYSJa1oVzLWKcO9cXEyz8-OetoSSJQPa36upmt38U7cpy-NvfWNTDRWUab_2Vu_abtGfJGLgxIXd-Vy_YJSxvoeH_nbQuQ') OR (([Extent1].[DeviceRegistrationId] IS NULL) AND ('01_SsH8BmeM:APA91bGdX01Uvo24qtjayPwePB3L6AWpoqTaGkG0K8SoPOAYSJa1oVzLWKcO9cXEyz8-OetoSSJQPa36upmt38U7cpy-NvfWNTDRWUab_2Vu_abtGfJGLgxIXd-Vy_YJSxvoeH_nbQuQ' IS NULL)))


Or else simply try the following query and try changing the parameter values

select DATEDIFF (second, '2019-09-05 10:20:28.727', '2019-09-05 10:21:28.727')