Thursday, 2 May 2024

Difference between IEnumerable,IQueryable VS List

 First the difference between List<T>, IEnumerable<T> and IQueryable<T>.

 The content of List<T> will always be loaded into memory, because it uses an array in the background.


The content of IEnumerable<T> will only load the requested item into the memory. Compiler sets up a state machine during compiling a method with IEnumerable<T> that has a yield return T. So only one item at a time will be loaded into memory in this case.


IQueryable<T> is "special" version of IEnumerable<T>. Specifically designed to query data sources, and implemented by data providers. Like EF, NHibernate. So when you tell EF to fetch the data with .ToListAsync<T>() EF will only then go the database and execute the generated query. See the docs for more info about IQueryable<T>.

Thursday, 28 December 2023

C# Enum Value and Display name Extension

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Web;

namespace Helper.Extensions
{
    public static class EnumExtensions
    {
        public static string GetEnumValue(this Enum enumValue)
        {
            var type = enumValue.GetType();
            var info = type.GetField(enumValue.ToString());
            if (info == null) return string.Empty;

            var da = (EnumMemberAttribute[])
                    (info.GetCustomAttributes(typeof(EnumMemberAttribute), false));

            if (da.Length > 0)
                return da[0].Value;
            else
                return string.Empty;
        }

        public static string GetDisplayName(this Enum enumValue)
        {
            return enumValue.GetType()
                            .GetMember(enumValue.ToString())
                            .First()
                            .GetCustomAttribute<DisplayAttribute>()
                            .GetName();
        }

    }
}

Friday, 4 August 2023

C# simple example for recursive call

using System;
class HelloWorld {
  static void Main() {
      var result=print(0);
    Console.WriteLine(result);
  }
  public static string print(int count)
  {
      return print2(count);
  }
  public static string print2(int count)
  {
      if(count <= 2)
      {
          Console.WriteLine(count);
          count++;
          //recursive call upto 3count
          return print(count);
      }
     
      return "Recursive final return";
  }
}

//output like below
0
1
2
Recursive final return

Friday, 21 July 2023

Mapster over AutoMapper for mapping objects in c# Crud

1.Add Mapster packages from NuGet

<package id="Mapster" version="7.3.0" targetFramework="net48" />
<package id="Mapster.Core" version="1.2.0" targetFramework="net48" />

2.Create Source class

//Source or DTO
public class TempCacheDto
    {
        public int Id { get; set; }

        public string SerialNumber { get; set; }
    }

3.Create Destination class

//Destination or Entity Db object
public class TempCache
    {
        public int Id { get; set; }

        public string SerialNumber { get; set; }
    }

4.Create Service or repository class where mapping required to convert Dto to Enity object.

Simple Save and Retrieve example below for using mapster and entity framework.


using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TempCache.Repositories
{
    public class TempCacheRepository
    {
//save data from dto model to entity using mapster        
        public bool Save(TempCacheModel bcTempCache)
        {
            using (var context = new DbContext())
            {

                if (bcTempCache.Id == 0)
                {
                    TempCache entity = bcTempCache.Adapt<TempCache>();
                    context.TempCaches.Add(entity);
                }
                else
                {
                    TempCache exist = context.TempCaches
                                        .FirstOrDefault(x => x.Id == bcTempCache.Id);
                    if (exist != null)
                    {
                        exist = bcTempCache.Adapt<TempCacheModel, TempCache>(exist);
                    }
                    else
                    {
                        return false;
                    }
                }
                context.SaveChanges();
                return true;
            }
        }
//get list from Db and retun as dto list using mapster
        public List<TempCacheModel> TempCaches()
        {
            using (var context = new DbContext())
            {
                return context.TempCaches.ToList().Adapt<List<TempCacheModel>>();
            }
        }
//get list from Db and retun as dto list using mapster        
        public TempCacheModel GetById(int id)
        {
            using (var context = new DbContext())
            {
                return context.TempCaches.FirstOrDefault(x=>x.Id==slNo)?
                        .Adapt<TempCacheModel>();
            }
        }
    }
}

Why Mapster over Auto mapper

MethodMeanStdDevErrorGen 0Gen 1Gen 2Allocated
'Mapster 6.0.0'108.59 ms1.198 ms1.811 ms31000.0000--124.36 MB
'Mapster 6.0.0 (Roslyn)'38.45 ms0.494 ms0.830 ms31142.8571--124.36 MB
'Mapster 6.0.0 (FEC)'37.03 ms0.281 ms0.472 ms29642.8571--118.26 MB
'Mapster 6.0.0 (Codegen)'34.16 ms0.209 ms0.316 ms31133.3333--124.36 MB
'ExpressMapper 1.9.1'205.78 ms5.357 ms8.098 ms59000.0000--236.51 MB
'AutoMapper 10.0.0'420.97 ms23.266 ms35.174 ms87000.0000--350.95 MB


Tuesday, 10 January 2023

Azure Cosmo DB

 Azure Cosmo DB used to store non Sql data that is collection of objects.

Important key stack properties are id and partition key.

Partition Key is kind of grouping / or like disk drive C, D drive in our PC,Lap.

Make sure partition key as perfect column Ex: need to retrieve data frequently day wise means then i will make CreatedDate as partition key (CreatedDate= DateTime.UtcNow.Date) 

id: its mandatory property & non-nullable

Unique/Primary key: will be combination of Partition Key + id

we can insert same id again but it's partition should be different. also, we can store different type of object but that object should contain same id and partition key.

Hierarchy: Example based OrderGroups is container


-->Data Base 

    |__ Container: kind of table or entity name

            |__ Items: Kind of Table Entity values

            |__Stored Procedure

            |__User Defined Functions & Stored Procedure

            |__ Triggers


Monday, 5 September 2022

Database SQL Concepts & key concepts to learn #inprogress

1. Constraints

2. Data Types

3.Diff between where and having clause

1. WHERE Clause is used to filter the records from the table based on the specified condition.HAVING Clause is used to filter record from the groups based on the specified condition.
2.WHERE Clause can be used without GROUP BY ClauseHAVING Clause cannot be used without GROUP BY Clause
3.WHERE Clause implements in row operationsHAVING Clause implements in column operation
4.WHERE Clause cannot contain aggregate functionHAVING Clause can contain aggregate function
5.WHERE Clause can be used with SELECT, UPDATE, DELETE statement.HAVING Clause can only be used with SELECT statement.
6.WHERE Clause is used before GROUP BY ClauseHAVING Clause is used after GROUP BY Clause
7.WHERE Clause is used with single row function like UPPER, LOWER etc.
SELECT COUNT(CustomerID), Country
FROM Customers
where Country='Brazil' or Country!='France'
GROUP BY Country
HAVING COUNT(CustomerID) > 5;
HAVING Clause is used with multiple row function like SUM, COUNT etc.
Below result first group by Country then filter from group data.
SELECT COUNT(CustomerID), Country
FROM Customers
GROUP BY Country
HAVING COUNT(CustomerID) > 5;


4.Temp table Vs CTE (common table expression) Vs Table variable

Temp tables: are created in tempdb, it contains two types #local & ##Global

These tables act as the normal table and also can have constraints, an index like normal tables.

#local temp tables available only for within session alone.

CREATE TABLE #LocalTemp
(
 UserID int,
 Name varchar(50), 
 Address varchar(150)
)
GO
insert into #LocalTemp values ( 1, 'Shailendra','Noida');

##Global temp tables can access to all sessions.

CREATE TABLE ##GlobalTemp
(
 UserID int,
 Name varchar(50), 
 Address varchar(150)
)
GO
insert into ##GlobalTemp values ( 1, 'Shailendra','Noida');
GO
Select * from ##GlobalTemp

CTE: CTE is a named temporary result set which is used to manipulate the complex sub-queries data. This exists for the scope of a statement. This is created in memory rather than the Tempdb database. we cannot create an index on CTE 

CTE improves readability and ease in maintenance of complex queries and sub-queries. Always begin CTE with a semicolon.

;With CTE1(Address, Name, Age)--Column names for CTE, which are optional
AS
(
SELECT Addr.Address, Emp.Name, Emp.Age from Address Addr
INNER JOIN EMP Emp ON Emp.EID = Addr.EID
)
SELECT * FROM CTE1 --Using CTE 
WHERE CTE1.Age > 50
ORDER BY CTE1.NAME

Table Variable: This acts like a variable and exists for a particular batch of query execution. It gets dropped once it comes out of the batch. This is also created in the tempdb database but not the memory. This also allows you to create a primary key, identity at the time of Table variable declaration but not non-clustered index.

GO
 DECLARE @TProduct TABLE
 (
 SNo INT IDENTITY(1,1),
 ProductID INT,
 Qty INT
 ) 
 --Insert data to Table variable @Product 
 INSERT INTO @TProduct(ProductID,Qty)
 SELECT DISTINCT ProductID, Qty FROM ProductsSales ORDER BY ProductID ASC 
 --Select data
 Select * from @TProduct
 
 --Next batch
 GO
 Select * from @TProduct --gives error in next batch

5.Indexes

Indexes are special lookup tables that the database search engine can use to speed up data retrieval. Simply put, an index is a pointer to data in a table. An index in a database is very similar to an index in the back of a book.

6.ACID: properties

A- Atomicity : fail or success it should apply for all transaction not partial.

7. Joins

    i. Inner Join : retrieve only matched rows between tables

    ii. Outer Join : retrieve only Not matched rows between tables

    iii. Left Join : Table A Left join Table B => Retrieve all from Table A and Only Matched rows                     From  Table B.

    iv. Right Join: Vice versa of Left join

8. Union(without duplicate rows) Vs Union All (include duplicate rows)


 

Global Exception Handler in c# .Net Core

 Default exception will handled by ExceptionFilter, incase we need to override this then we can derived from IExceptionFilter and we can customize it.

Predefined interface for Exception filter is below


///predefine interface for exception is below
namespace Microsoft.AspNetCore.Mvc.Filters
{
    //
    // Summary:
    //     A filter that runs after an action has thrown an System.Exception.
    public interface IExceptionFilter : IFilterMetadata
    {
        //
        // Summary:
        //     Called after an action has thrown an System.Exception.
        //
        // Parameters:
        //   context:
        //     The Microsoft.AspNetCore.Mvc.Filters.ExceptionContext.
        void OnException(ExceptionContext context);
    }
}


Let us create a class and inherit from IExceptionFilter file name like GlobalExceptionFilter.cs

Above interface contains  OnException  method so when we derived from tat interface we need to provide definition.



using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Net;
namespace GlobalException
{
public class GlobalExceptionFilter : IExceptionFilter
{

    /// <summary>
    /// Global method to log the Exception thismethod will hit when exception happen
    /// </summary>
    /// <param name="context"></param>
    public void OnException(ExceptionContext context)
    {
        if (context != null)
        {
            /// Find the response status code if it's null then send InternalServerError
            HttpStatusCode statusCode = (context.Exception as WebException != null &&
                        ((HttpWebResponse)(context.Exception as WebException).Response) != null) ?
                        ((HttpWebResponse)(context.Exception as WebException).Response).StatusCode
                        : HttpStatusCode.InternalServerError;

            context.ExceptionHandled = true;
            HttpResponse response = context.HttpContext.Response;
            response.StatusCode = (int)statusCode;
            response.ContentType = "application/json";
            /// use own logger to store exception like below
            //logger.Error(context.Exception);


        }
    }            
}
}

Now we need create Startup.cs class and map in program.cs file like below.

 public class Program
    {
        protected Program()
        {

        }
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

we mentioned above like all configuration based on Startup class.

Now startup class we need add like below.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NLog;
using NLog.Extensions.Logging;
using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Mvc.NewtonsoftJson;
using System;

namespace GlobalExceptionSample.API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            var config = new ConfigurationBuilder()
          .SetBasePath(System.IO.Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();

            LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));

            Configuration = configuration;
           
        }

        public static IConfiguration Configuration { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            ///any default implementation we can include as AddSingleton like below
            ///services.AddSingleton<ILog, Log>();
            /*----Here we are adding Global Exception filter as GlobalExceptionFilter*/
            services.AddMvc(config => {
                            config.Filters.Add(typeof(GlobalExceptionFilter));
                         });

            services.AddControllers()
                    .AddNewtonsoftJson(options =>
                    {
                        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                    });

            services.AddCors();
            services.AddAuthentication(IISDefaults.AuthenticationScheme);
           
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseAuthentication();
            app.UseRouting();
            app.UseCors(
              options => options.SetIsOriginAllowed(x => _ = true)
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials());
            app.UseAuthorization();
           
        }
    }
}

so in startup class below highlighted code is called exception filter config.

services.AddMvc(config => {
                            config.Filters.Add(typeof(GlobalExceptionFilter));
                         });