Method vs Linq based query syntax example

I need to make inner join on 3 tables; LedgerTypes, LedgerControl and Ledger.

Method based query example

//method based query
            
// your starting point - table in the "from" statement
var list = LedgerTypes
  //the source table of the inner join
  .Join(LedgerControl,
     //primary key (first part of sql "join" statement)
     t => t.Id,
     //foreign key (the second part of the "on" clause)
     lc => lc.ControllerTypeId, 
  (t, lc) => new { t, lc })   //new join
  // third table in the join clause
  .Join(Ledger, 
    //third table foreign key
    tc => tc.lc.Id, 
    //second table primary key
    l => l.ControllerID, 
  (tc, l) => new { tc, l })
      .Select(result => new {          //selection
       LedgerTypeId = result.tc.t.Id,
       LedgerTypeName = result.tc.t.ControllerTypeName,
       LedgerControlId = result.tc.lc.Id,
       LedgerControlName = result.tc.lc.ControllerCodeFullName,
       LedgerId = result.tc.lc.Id,
       LedgerName = result.tc.lc.ControllerCodeFullName
       // other assignments
});

Linq based query example

 //linq based query
var list = from t in LedgerTypes
    join lc in LedgerControl on t.Id equals lc.ControllerTypeId
    join l in Ledger on lc.Id equals l.ControllerID
    select new
       {
             LedgerTypeId = t.Id,
             LedgerTypeName = t.ControllerTypeName,
             LedgerControlId = lc.Id,
             LedgerControlName = lc.ControllerCodeFullName,
             LedgerId = l.Id,
             LedgerName = l.LedgerCodeFullName
            // other assignments
       };

I prefer query syntax because it’s readable and maintainable.

Resources

For more info read here and here

Simplifying ADO.NET Code in .NET 6

When developers think of how to access data, many use the Entity Framework (EF), Dapper, NHibernate, or some other object-relational mapper (ORM). Each of these ORMs use ADO.NET to submit their SQL queries to the back-end database. So, why do many developers use ORMs instead of just using ADO.NET directly? Simply put, ORMs allow you to write. If each of these ORMs are simply wrappers around ADO.NET, can you write your own wrapper to cut down the amount of code you need to write? Absolutely! This series of articles shows you how to create a set of reusable wrapper classes to make it simpler to work with ADO.NET in .NET 6.

Read more on CodeMag web site here;

Simplifying ADO.NET Code in .NET 6: Part 1

Simplifying ADO.NET Code in .NET 6: Part II (Coming soon)

AutoMapper in .NET 6

Adding AutoMapper to ASP.NET 6 application;

dotnet add package AutoMapper --version 10.1.1
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection --version 8.1.1

The next step is adding the AutoMapper to our DI container, inside the program.cs we need to add the following;

builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

Now its time to create our AutoMapper profiles, so on the root directory of our application we need to create AutoMapperProfile.cs

We are going to map the below entity (“User”) to the a Dto (“UserDto”)

public class User
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public DateTime DateOfBirth { get; set; }
        public string Country { get; set; }
        public string Address { get; set; }
        public string MobileNumber { get; set; }
        public string Sex { get; set; }
    }
public class UserDto
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string DateOfBirth { get; set; }
        public string Country { get; set; }
    }
}

Now inside the AutoMapperProfile class we need to add the following

public class AutoMapperProfile : Profile
    {
        public AutoMapperProfile()
        {
            CreateMap<UserDto, User>()
                .ForMember(
                    dest => dest.FirstName,
                    opt => opt.MapFrom(src => $"{src.FirstName}")
                )
                .ForMember(
                    dest => dest.LastName,
                    opt => opt.MapFrom(src => $"{src.LastName}")
                )
                .ForMember(
                    dest => dest.Email,
                    opt => opt.MapFrom(src => $"{src.Email}")
                )
                .ForMember(
                    dest => Convert.ToDateTime(dest.DateOfBirth),
                    opt => opt.MapFrom(src => $"{src.DateOfBirth}")
                )
                .ForMember(
                    dest => dest.Phone,
                    opt => opt.MapFrom(src => $"{src.Phone}")
                )
                .ForMember(
                    dest => dest.Country,
                    opt => opt.MapFrom(src => $"{src.Country}")
                )
                .ForMember(
                    dest => dest.Status,
                    opt => opt.MapFrom(src => 1)
                );
        }
    }

The AutoMapperProfile class MUST inherit from Profile class in order for AutoMapper to recognise it.

Inside the constructor we define the mapping between the Entity and the Dto.

Once we complete our profile mapping its now to utilise our new map in our controller.

public class UsersController : ControllerBase
{
    public IUnitOfWork _unitOfWork;
    // define the mapper
    public readonly IMapper _mapper;

    // initialise the dependencies with constructor initialisation
    public UsersController(
        IMapper mapper,
        IUnitOfWork unitOfWork)
    {   
        _mapper = mapper;
        _unitOfWork = unitOfWork;
    }

    [HttpPost]
    public async Task<IActionResult> AddUser(UserDto user)
    {
        // utilise the mapping :)
        var _mappedUser = _mapper.Map<User>(user);

        await _unitOfWork.Users.Add(_mappedUser);
        await _unitOfWork.CompleteAsync();

        var result = new Result<UserDto>();
        result.Content = user;

        return CreatedAtRoute("GetUser", new { id = _mappedUser.Id}, result); // return a 201
    }
}

So basically we need to initialise the mapper with constructor initialisation.

Then we need to utilise as follow

var _mappedUser = _mapper.Map<Entity>(dto);

AutoMapper is a powerful tool to keep in our toolset.

JSON Circular Reference Loop Error running Raw SQL in Web API using EF Core

I had a complex stored procedure that I needed to run using EF core in a Web API project. I cannot use LINQ to represent this query. I have followed all best practices outlined here;

Everything worked great except raw sql endpoint. It started giving me “Circular Reference loop error”. To keep thing simple, I am returning DTO from endpoint not the entity.

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'task' with type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Collections.Generic.IEnumerable`1[FM.Service.Shared.DTO.TranMasterViewDto],FM.Service.LedgerTranViewService+<GetTransactionForProjectActionAsync>d__4]'. Path 'stateMachine.<>t__builder'
......

Here is my configuration before and after the fix;

Newtonsoft Configuration in program.cs file before the fix;
}).AddNewtonsoftJson()
Newtonsoft Configuration in program.cs file after the fix;
}).AddNewtonsoftJson(
    options => 
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)

The error is gone and I am getting this results.

{
    "stateMachine": {
        "<>1__state": 0,
        "<>t__builder": {},
        "projectActionID": "82ee5154-971a-ed11-90e6-00155d717606",
        "trackChanges": false,
        "<>4__this": {}
    },
    "context": {},
    "moveNextAction": {
        "method": {
            "name": "MoveNext",

Wait…This is not what I expected. Why I am getting Tasks result where I need to see my Dto results.

It turns out that I am not returning results from my Async method but the task;

public async Task<IActionResult> GetTransactionForProjectActionAsync(Guid projectActionId)
{
   return Ok(_service.LedgerTranViewService.GetTransactionForProjectActionAsync(projectActionId, trackChanges: false));
        }

Fixing the return type has solved all of my problems;

return Ok(_service.LedgerTranViewService.GetTransactionForProjectActionAsync(projectActionId, trackChanges: false).Result);
        }
[
    {
        "id": 20221,
        "projectActionID": "82ee5154-971a-ed11-90e6-00155d717606",        
        "tranMasterDetail": [
            {
                "tranMasterId": "9358b0c5-6d30-ed11-90e8-00155d717606",
                "ledgerID": "63302216-0946-ea11-ac82-f81654967f7a",
                "tranDescription": "Rent paid",
                "tranDate": "2022-01-03T00:00:00",
                "tranFlag": 0,
                "tranAmount": 1300.00
            }
        ]
    }
]

Remove Newtonsoft ReferenceLoopHandler from program.cs file.

}).AddNewtonsoftJson()

Hope this will help someone.

Reference

https://stackoverflow.com/questions/62985907/avoid-or-control-circular-references-in-entity-framework-core

Adding byte to byte array

There are two methods. either to create a new array or resize the existing array;

To resize existing array, do this;

Array.Resize(ref fileBytesArray, fileBytesArray.Length + 1);

To create a new array from existing one and resize, do this;

bArray = AddByteToArray(bArray,  newByte);

Here is the method;

public byte[] AddByteToArray(byte[] bArray, byte newByte)
{
    byte[] newArray = new byte[bArray.Length + 1];
    bArray.CopyTo(newArray, 1);
    newArray[0] = newByte;
    return newArray;
}

Reference

c# how to add byte to byte array