Thursday, April 28, 2016

Dapper.net-a light weight ORM

Dapper.net-a light weight ORM


I and my friend Gaurav has written this blog. We used Dapper.net in out project and found that when this is effectively used, it also causes performance gain.

Introduction

ORMs helps to flow data from relational database to object models. We are aware of many ORMs like LINQ-To-SQL, Entity Framework etc. They all have some pros and cons.

Dapper.net is a newly introduces light weight ORM. This is simple to use and is better performing hence getting popular now-a-days.

This is free open source software and distributed under dual license, either the Apache License 2.0 or the MIT License. Dapper was started by Sam Saffron and Marc Gravell for StackOverflow and is used by it.

Dapper is a micro-ORM i.e. it does not offer the full range of features of a full ORM such as Entity Framework. This is by design. It focuses on simplicity and performance rather than full automation. Dapper does not generate the SQL queries, but only maps the result to Plain Old CLR Objects (POCOs). Single class ORM is available on NUget.


Dapper's primary feature is mapping from .NET classes to database tables. Dapper is implemented as a series of Extension Methods which can be called on any object which implements the IDbConnection. This is compatible with any database which implement provider for .net (Idbconnection implementation).

We have emphasized below key features in this blog
  • 1.       Speed and fast in performance
  • 2.       Fewer lines of code
  • 3.       Static and dynamic object binding
  • 4.       Easy handling of SQL queries and stored procedures
  • 5.       Operating directly to IDBConnection class so that running queries directly on database instead of passing data through various objects like that in entity framework.
  • 6.       Multiple query support.
  • 7.       Bulk data insert.
  • 8.       Fetching multiple data at a time
  • 9.       Transaction support

Dapper has no DB specific implementation details, it works across all .NET ADO providers including SQLite, SQL CE, Firebird, Oracle, MySQL, PostgreSQL and SQL Server.

People shifted to ORMs because EF like ORMs generated queries under the hood and developer do not need all skills to write a sql query for complex operations. EF query language is simple and object based and easy to understand. Dapper.net does not generates queries for us. This can be one of the drawback of dapper.net. However it is faster over EF and other ORMs which is proved on many links. We can get the performance boost in our application by using dapper.net or we can decide its smart use in our application in combination of entity framework or other ORM and can get best performance benefits wherever we need a performance improvement.

Stack Overflow is the main site which is using dapper.net.

Extension methods provided by dapper.net

Once we declare IDBConnection object, we are ready for using dapper functionality. Note that all extension methods assume the connection is already open, they will fail if the connection is closed.

private IDbConnection _db = new SqlConnection("Data Source=; Database=; Integrated Security=True;");


Below is first extension method which is returning strongly types object results. It executes the query and maps the results to strongly type objects.


public static IEnumerable Query(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)


Below is extension method which executes query and maps the result to dynamic objects.

public static IEnumerable Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)


Below is helper extension method which executes query and do not return results. This is used for creating database, tables, insert, update and delete operations.

public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)


CRUD Operations using dapper.net

Select operation

Query result maps to strongly typed object Example

Select list of all employees is just a simple call as below. It is returning strongly typed object provided we match the Employee class to database Employee table.
public List GetAll()
        {
            List empList = this._db.Query("SELECT * FROM Employee").ToList();
            return empList;
        }

Find query is very simple and it is not returning any exception if I do not have matching record in database.
public List Find(string findString)
        {
            string query = "SELECT * FROM Employee WHERE EmpName like '%" + findString + "%'";
            return this._db.Query(query).ToList();
        }

Complex queries where data is coming from two different tables with some join, example:-
public class Product
{
    public int ProductID { get; set; }
    public string Name { get; set; }
    public string ProductNumber { get; set; }
    public DateTime ModifiedDate { get; set; }

    public SubCategory SubCategory { get; set; }
}

public IEnumerable SelectProductsWithSubCategories()
{
    using (IDbConnection connection = OpenConnection())
    {
        const string query = "SELECT p.ProductID, p.Name, p.ProductNumber,  p.ModifiedDate, " +
              "s.ProductSubcategoryId AS Id, s.ProductCategoryID AS CategoryId, " +
              "s.[Name], s.ModifiedDate AS ModifiedOn " +
              "FROM Production.Product p " +
              "LEFT OUTER JOIN Production.ProductSubcategory " +
              "s ON s.ProductSubcategoryId = p.ProductSubcategoryID";
       
        return connection.Query(query,
          (product, subCategory) => { product.SubCategory = subCategory; return product; });
    }
}

Query result maps to dynamic objects Example

Example of dynamic results mapping
public IEnumerable FindWithDynamicSupport(string findString)
        {
            string query = "SELECT EmpId,EmpName FROM Employee WHERE EmpName like '%" + findString + "%'";
            return this._db.Query(query);
        }

private void button2_Click(object sender, EventArgs e)
        {
            string displayResult = "";
            var results = _board.FindWithDynamicSupport(textBoxFind.Text);
            foreach (var row in results)
            {
                 displayResult += row.EmpId + " " + row.EmpName + "\n";
            }
            MessageBox.Show(displayResult);
        }

Multiple query support

Dapper allows you to process multiple result grids in a single query.

var sql = @"select * from Customers where CustomerId = @id
                      select * from Orders where CustomerId = @id
                      select * from Returns where CustomerId = @id";

using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
   var customer = multi.Read().Single();
   var orders = multi.Read().ToList();
   var returns = multi.Read().ToList();
   ...
}

Select using stored procedure

Dapper fully supports stored procs.

var user = cnn.Query("spGetUser", new {Id = 1},
        commandType: CommandType.StoredProcedure).SingleOrDefault();

//or with more fancy way

var p = new DynamicParameters();
p.Add("@a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

cnn.Execute("spMagicProc", p, commandType: CommandType.StoredProcedure);

int b = p.Get("@b");
int c = p.Get("@c");

Support for IEnumerable parameter to the query

Dapper allow you to pass in IEnumerable and will automatically parameterize your query. E.g.

connection.Query("select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids", new { Ids = new int[] { 1, 2, 3 });

//this is translated to the query as below
//select * from (select 1 as Id union all select 2 union all select 3) as X where Id in (@Ids1, @Ids2, @Ids3)"
// @Ids1 = 1 ,@Ids2 = 2 , @Ids2 = 3


Insert Operation

Dapper.net allows us to execute a command multiple times like below.

connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
  ).IsEqualTo(3);

// 3 rows inserted: "1,1", "2,2" and "3,3"

This works for any parameter that implements IEnumerable for some T.

Bulk Insert

Dapper.net has simplified the bulk insert queries. Look at below sample:-
  public void BulkInsert()
        {
            List list = new List() { new Employee() { EmpName = "Name1", EmpScore = 12 }, new Employee() { EmpName = "Name2", EmpScore = 13 } };
            var sqlQuery = "INSERT INTO Employee (EmpName, EmpScore) VALUES (@EmpName, @EmpScore); ";
             var result =  this._db.Execute(sqlQuery, list);
        }

Delete Operation

Using Execute extension for Remove operation, dapper.net has provided the delete functionality. Example is as below.
  public void Remove(int id)
        {
            var sqlQuery = ("Delete From Employee Where EmpID = " + id + "");
            this._db.Execute(sqlQuery);
        }


Create Operations

Dapper.net has not provided create table functionality.

  

Transaction Support

Dapper also supports transactional operations. Syntax for transaction start and commit is as below. Execute the dapper.net queries in after starting transaction and have commit on successful execution.
IDbTransaction transaction = connection.BeginTransaction();
;
;
transaction.Commit();

Statistics

A key feature of Dapper is performance. The metrics shows statistics taken from github website provided by dapper.net people itself.

Reference Links

https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper.Tests/PerformanceTests.cs


Sample
public interface IEmployeeDashBoard
    {
        List GetAll();
        List Find(string findText);
        Employee Add(Employee employee);
        Employee Update(Employee employee);
        void Remove(int id);
        IEnumerable FindWithDynamicSupport(string findString);
    }

 public class EmployeeDashBoard : IEmployeeDashBoard
    {
        private IDbConnection _db; // = new SqlConnection("Data Source=pallavi-kul-LAP\\MSSQL2008; Database= test; Integrated Security=True;");
        public EmployeeDashBoard(string connectionString)
        {
            _db = new SqlConnection(connectionString);
        }        

        public List GetAll()
        {
            List empList = this._db.Query("SELECT * FROM Employee").ToList();
            return empList;
        }

        public List Find(string findString)
        {
            string query = "SELECT * FROM Employee WHERE EmpName like '%" + findString + "%'";
            return this._db.Query(query).ToList();
        }

        public IEnumerable FindWithDynamicSupport(string findString)
        {
            string query = "SELECT EmpId,EmpName FROM Employee WHERE EmpName like '%" + findString + "%'";
            return this._db.Query(query);
        }

        public Employee Add(Employee employee)
        {
            var sqlQuery = "INSERT INTO Employee (EmpName, EmpScore) VALUES (@EmpName, @EmpScore); " + "SELECT CAST(SCOPE_IDENTITY() as int)";
            var employeeId = this._db.Query(sqlQuery, employee).Single();
            employee.EmpID = employeeId;
            return employee;
        }

        public void BulkInsert()
        {
            List list = new List() { new Employee() { EmpName = "Name1", EmpScore = 12 }, new Employee() { EmpName = "Name2", EmpScore = 13 } };
            var sqlQuery = "INSERT INTO Employee (EmpName, EmpScore) VALUES (@EmpName, @EmpScore); ";
             var result =  this._db.Execute(sqlQuery, list);
        }

        public string AddUsingSPN(Employee employee)
        {
            var p = new DynamicParameters();
            p.Add("EmpName", employee.EmpName, null, ParameterDirection.Input, 50);
            p.Add("EmpScore", employee.EmpScore, null, ParameterDirection.Input);
            p.Add("EmpUpdatedName", null, DbType.AnsiString, ParameterDirection.Output, 50);
            p.Add("EmpJoiningDate", null, DbType.DateTime, ParameterDirection.Output);

            this._db.Query("CreateEmployeeRecord", p, commandType: CommandType.StoredProcedure);
            string name = p.Get("EmpUpdatedName");
            DateTime date = p.Get("EmpJoiningDate");
            return name;
        }

        public string QueryMultiplePOC(int i = 4)
        {
            var p = new DynamicParameters();
            p.Add("a", i);
            p.Add("r", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
            var grid = _db.QueryMultiple("spEcho", p, commandType: CommandType.StoredProcedure);

            var result1 = grid.Read>(
                              (a, b) => Tuple.Create((object)a, (object)b)).ToList();
            var result2 = grid.Read>(
                              (a, b) => Tuple.Create((object)a, (object)b)).ToList();

            return ((int)(result1[0].Item1.Id)) + " | " + ((int)(result1[0].Item2.Id));
        }

        public Employee Update(Employee employee)
        {
            var sqlQuery =
            "UPDATE Employee " +
            "SET EmpName = @EmpName, " +
            " EmpScore = @EmpScore " +
            "WHERE EmpID = @EmpID";
            this._db.Execute(sqlQuery, employee);
            return employee;
        }

        public void Remove(int id)
        {
            var sqlQuery = ("Delete From Employee Where EmpID = " + id + "");
            this._db.Execute(sqlQuery);
        }
    }

//use
EmployeeDashBoard _board = new EmployeeDashBoard(textBoxConnectionstring.Text);

  private void RefreshListBox()
        {
            this.listBox1.DataSource = _board.GetAll();          
        }
 private void buttonRemove_Click(object sender, EventArgs e)
        {
            _board.Remove(((Employee)(listBox1.SelectedItem)).EmpID);
            RefreshListBox();
        }
private void buttonAddUsingSP_Click(object sender, EventArgs e)
        {
            var msg = _board.AddUsingSPN(new Employee(textBox1.Text, double.Parse(textBox2.Text)));
            MessageBox.Show(msg);
        }
  private void buttonQueryMultiplePOC_Click(object sender, EventArgs e)
        {
            /* ***************** below is SP ***********
        * create proc spEcho
           @a int
           as
           begin,

           select @a Id, 'ping' Name, 1 Id, 'pong1' Name
           select @a Id, 'ping' Name, 2 Id, 'pong2' Name
           return @a
           end
        * */
            /* ***************** Result ******************
             *
             *
             (1 row(s) affected)

            Id          Name Id          Name
            ----------- ---- ----------- -----
            3           ping 2           pong2

            (1 row(s) affected)

            Return Value
            ------------
            3

            (1 row(s) affected)


             * */

            MessageBox.Show(_board.QueryMultiplePOC());

        }

 private void buttonFind_Click(object sender, EventArgs e)
        {
            string textToFind = textBoxFind.Text;
            List empList = _board.Find(textToFind);
            MessageBox.Show(empList.Count.ToString());
        }

 private void buttonReEstablishConnection_Click(object sender, EventArgs e)
        {
            _board = new EmployeeDashBoard(textBoxConnectionstring.Text);
        }
 private void buttonFindWithDynamicSupport_Click(object sender, EventArgs e)
        {
            string displayResult = "";
            var results = _board.FindWithDynamicSupport(textBoxFind.Text);
            foreach (var row in results)
            {
                 displayResult += row.EmpId + " " + row.EmpName + "\n";
            }
            MessageBox.Show(displayResult);
        }
private void buttonBulkInsert_Click(object sender, EventArgs e)
        {
            _board.BulkInsert();
            RefreshListBox();
        }

Monday, October 5, 2015

Regular expressions to resolve different requirements

Issue 1>
I was having requirement that I want to find all words in two consecutive % characters. Below interesting regular expression I used for that.

%[\w\s\S]*?%

\w for alphabet and underscore
\s for space
\S for special chars
? returns shortest possible match

Edit the% my file % %% %kjghjhgkjg % % (**&*&*&*&*&*&*& % %9089898098% Expression

Highlighted are the matches.

http://regexr.com/3btui see for more details.

The c#.net code used as below to find all these matches.

            MatchCollection allMatchResults = null;
            var regexObj = new Regex(@"%[\w\s\S]*?%");  
            allMatchResults = regexObj.Matches(this.textBox1.Text);

            string output = "";
            foreach (var s in allMatchResults)
            {
                output += s + "\n";
            }

            label1.Text = output;

Friday, August 21, 2015

Getting "Must declare the scalar variable" error while writing SQL statements in script

I was writing bunch of operations in sql, was using SQL Server 2008 R2. I declared one INT variable and was trying to use inside select statement, I was getting error as "Must declare the scalar variable "@numberOfCards"."

SQL scripts looks like something similar to this: -


declare @numberOfCards int;
set @numberOfCards = 3; --some number
;
;
;
GO
select * from CardsRepository where CardsCount = @numberOfCards

Reason of issue:
Culprit was GO statement. The GO command signals the end of a batch of Transact-SQL statements. A local variable is only valid within the body of a batch or procedure.

Solution:

The first option is to remove the GO command between the 2 sets of scripts so that the local variable @numberOfCards is valid and accessible on both scripts. Use semi comma where ever the sql statement ends. 

Wednesday, April 1, 2015

Good serialization deserialization example in c# 4.0 (.Net 4.0)

Code of deserialization


           CarInfoCollection carInfoCollection = null;

            using (StringReader strReader = new StringReader(this.textBox.Text.Trim()))
            {
                using (XmlTextReader reader = new XmlTextReader(strReader))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(CarInfoCollection));
                    carInfoCollection = (CarInfoCollection)serializer.Deserialize(reader);
                    reader.Close();
                }
            }


            MessageBox.Show(carInfoCollection.CarInfoFields.Count().ToString());

----------------------------------------------------------------------------------------

Type classes

  [System.SerializableAttribute()]
    [XmlRootAttribute("CarInfoFields", Namespace = "urn:carinfo-schema:CarInfoCollection")]
    public class CarInfoCollection
    {
        [XmlElement("CarInfo")]
        public CarInfo[] CarInfoFields { get; set; }
    }

    [System.SerializableAttribute()]
    public class CarInfo
    {
        [XmlAttribute]
        public String Name { get; set; }

        [XmlAttribute]
        public CarUsage Usage { get; set; }

        [XmlArray(ElementName = "Features", IsNullable = true)]
        [XmlArrayItem(ElementName = "Feature", IsNullable = true)]
        public List<string> Features { get; set; }
    }

----------------------------------------------------------------------------------------

Xml string entered in textbox, examples




Serialization Example

When we do not want xml declaration / omit xml declaration

OmitXmlDeclaration should be set to True while initializing XmlWriter. Sample :-

  public string SerializeToXML(T typeToSerialize)
        {
            using (var sw = new StringWriter())
            {
                using (var xw = XmlWriter.Create(sw, new XmlWriterSettings { OmitXmlDeclaration = true }))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    
                    // below code will omit the namespace in serialized xml
                    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                    ns.Add("", "");
                    serializer.Serialize(xw, typeToSerialize, ns, encodingStyle: string.Empty);
                }
                return sw.ToString();
            }
        } 

Saturday, December 15, 2012

.Net 4.5 Features, what is new?



  • Cross-Platform Development with the .NET Framework


  • Portable class libraries on multiple platforms, such as Windows 7, Windows 8, Silverlight, Windows Phone, and Xbox 360. When you create a Portable Class Library project, you can choose two or more platforms you want to target. Link: http://msdn.microsoft.com/en-us/library/gg597391.aspx


  • Asynchronous file operation

  • In the .NET Framework 4.5, new asynchronous features were added to the C# and Visual Basic languages. These features add a task-based model for performing asynchronous operations. To use this new model, use the asynchronous methods in the I/O classes. 


  • perform resource-intensive I/O operations without blocking the main thread.
  • async method contains Async in its name such asReadAsync, WriteAsync, CopyToAsync, FlushAsync, ReadLineAsync, and ReadToEndAsync. These async methods are implemented on stream classes, such as Stream,FileStream, and MemoryStream, and on classes that are used for reading from or writing to streams, such TextReader and TextWriter
  • In th .NET Framework 4 and earlier versions, you have to use methods such as BeginRead and EndRead to implement asynchronous I/O operations. These methods are still available in the .NET Framework 4.5 to support legacy code; however, the async methods help you implement asynchronous I/O operations more easily.
  • Keywords – async (mark method which contains async operaion) and await (applies to result of async operation)

  • Ref URL : http://msdn.microsoft.com/en-us/library/kztecsys.aspx



  • Web
  • - Support for reading and writing HTTP requests and responses asynchronously.
    - Support for new HTML5 form types
    - Support for asynchronous modules and handlers.
    Ref URL : http://msdn.microsoft.com/en-us/library/hh420390.aspx



  • CLR and Framework improvements

  • a.    Ability to reduce system restarts by detecting and closing .NET Framework 4 applications during deployment
    b.    Support for arrays that are larger than 2 gigabytes (GB) on 64-bit platforms. This feature can be enabled in the application configuration file. Ref: element
    c.    Better performance through background garbage collection for servers.
    d.    ProfileOptimization - Background just-in-time (JIT) compilation, which is optionally available on multi-core processors to improve application performance. (Profile optimization requires a multicore computer. The methods are ignored on other computers.) Each time you initiate profile optimization in an application domain, the profile that was created during the previous use is read. The information in the profile is used to guide background compilation by identifying the methods that are most likely to be executed during startup. On multicore computers, this increases the chances that a method is already compiled by the time it is needed so that the main application thread does not have to call the JIT compiler.
    e.    Regex.MatchTimeout property - The MatchTimeout property defines the approximate maximum time interval for a Regex instance to execute a single matching operation before the operation times out.
    f.    Ability to define the default culture for an application domain
    g.    Zip compression improvements to reduce the size of a compressed file. See the System.IO.Compression namespace.
    h.    Type reflection support split between Type and TypeInfo classes




  • Improved Garbage Collection


  • Background GC available to server application also in .Net 4.5
    Before version 4, the .NET Framework provided a concurrent GC mode that performed full GCs concurrently with user code (vs. blocking, which pauses all user threads), thus reducing pause time for full GCs.

    In the .NET Framework 4, Microsoft delivered an improved version called the background workstation garbage collection, which reduced latency but only benefited client apps.

    In the .NET Framework 4.5, Microsoft have delivered background server garbage collection, which is typically used for server apps. As a result, all apps now have background GC available to them, regardless of which GC they use.
    This results in much shorter pauses on server.

    Higher throughput
    For server GC, there’s one heap per logical processor.
    When one of the heaps runs out of space for allocations, it triggers a GC. Usually, server apps have a pool of worker threads that perform similar types of tasks, and roughly the same amount of memory is allocated per thread, which results in naturally balanced managed heaps. If this is not the case, and one thread allocates a lot more memory than other threads, the heap that corresponds to its CPU runs out of space to allocate quickly and triggers a GC. GC has a “heap balancing” mechanism to help these apps.

    In the .NET Framework 4 and earlier versions, the small object heap (SOH) was balanced, but the large object heap (LOH) was not, so imbalanced LOH allocations in server GC would trigger more full GCs . In the .NET Framework 4.5, the server GC allocator balances the allocations across the heaps when it finds that GC heaps, including both SOH and LOH, are not balanced. In apps that begin to develop imbalanced heaps, this mechanism eliminates unnecessary GCs. This reduces the total time spent in GC and improves the app throughput.

    GC support for latest hardware
    Starting with Windows 7 and Windows Server 2008 R2, Windows supports more than 64 processors on a single computer. For machines that have very large numbers of processors (more than 64), the operating system splits the processors into multiple processor groups. In the .NET Framework 4.5, the GC can view CPUs across processor groups and takes all the cores into account when creating and balancing heaps.

    You’ll need to enable the element in your app’s configuration file to turn this behavior on. GC automatically detects and enables NUMA support. (NUMA – Non uniform memory access)

    SustainedLowLatency
    Stock market kind of application cannot tolerate pauses.

    In the .NET Framework 4.5, Microsoft has provided the option by introducing SustainedLowLatency mode, which avoids full blocking GCs. This mode is also available for the workstation GC in the .NET Framework 4 via Update 4.0.3. While the SustainedLowLatency setting is in effect, generation 0, generation 1, and background generation 2 collections still occur and do not typically cause noticeable pause times. blocking generation 2 collection happens only if the machine is low in memory or if the app induces a GC by calling GC.Collect().

    In the .NET Framework 4.5, SustainedLowLatency mode is available for both workstation and server GC. To turn it on, set the GCSettings.LatencyMode property to GCLatencyMode.SustainedLowLatency. The .NET Framework 4 includes aLowLatency mode for workstation GC; however, this setting is only intended to be used for short periods of time, whereasSustainedLowLatency mode is intended to be used for much longer.

    Applications work with large datasets where user objects > 2 GB
    In earlier versions of the .NET Framework, the following lines of code throw OutOMemoryException exceptions due to the 2-GB limit on object sizes on the GC heap. In the .NET Framework 4.5, the code succeeds, assuming that there is enough physical memory available on the machine:

    new Object[1000000000]; //(approximate size of this array 8 GB)
    new int[50000,50000]; //(approximate size of this array is 10 GB)
    new Dictionary(1000000000); //(approximate underlying array size is 24 GB)


    Note that the array index is still a 32-bit number. By default, the .NET Framework does not support arrays that are greater than 2 GB, but in the .NET Framework 4.5, you can use the element in your application configuration file to enable arrays that are greater than this size.

    Sunday, June 10, 2012

    Playing with Constructors (c# 4.0) (Examples in VS 2010)

    Constructors are class methods which executes when class object is created. 
    Constructors can be marked as public, private, protected, internal, protected internal, static.
    Classes can have multiple constructors. If we do not specify constructor, c# will create default one.

    Scenario 1: Inheritance and default constructors

    When we inherit base class (Base1) in child class (Base2), and create an object of child class, it executes base class constructor first and child class constructor later. This helps that when child class constructor is executing, system makes sure that base class has already set properties or initializations and then child class can re-set those according to need. Refer below example for this:

    class Base1
    {
        public Base1()
        {   Console.WriteLine("Base 1 .ctor called");
        }
    }
    class Base2 : Base1
    {
        public Base2()
        {   Console.WriteLine("Base 2 .ctor called");
        }
    }

    Actual call is
    Base2 base2Obj = new Base2(); or
    Base1 base1Obj = new Base2();

    Output is

    Base 1 .ctor called
    Base 2 .ctor called

    Even if you write base2 constructor as below, output will be the same as mentioned above.

    public Base2() : base()
    {       
         Console.WriteLine("Base 2 .ctor called");
    }

    Conclusion:

    It always the base class costructor that  get called first. Derived class may not like the way that the base class has been initialized. It can change the initial value of data provided that it has access to do so.