CodeTrigger  

Code Generation For C#, WPF, WCF, SQL SERVER/ORACLE/MYSQL and Visual Studio 2013-2019

Tutorial - Generating a sample repository-pattern test application with CodeTrigger
To work with these sample projects you will need CodeTrigger installed, Visual Studio 2013-2017, and a test database with some data.
Follow these steps below to generate a multi-tier (testclient/businesslayer/datalayer) application using the repository pattern
This guide has been updated for version 5.1.0.0 (released June 10th 2017)

Microsoft Northwind Sample db

Step 1 - Ensure you have a relevant test database

The CodeTrigger sample applications are designed to work with your existing database schema to ensure that the samples are as relevant as possible. Ensure that you have a TEST SQL Server/Oracle/MYSQL database handy. CodeTrigger and its associated supplier companies do not accept any liability for data loss whilst using the CodeTrigger product. It is important that you use a test database until you are familiar with the functionality of the generated code.

Step 2 - Create a new CodeTrigger project

Create a new Multi-tier application using the wizard. As a guide you can use the 'DB to Microservice' wizard. Name your project SampleRepositoryPattern and generate your application as usual, using CodeTrigger.

Step 3 - Choose the following settings in the Advanced options tab

Generate interface definitions: Ticked
Generate using repository pattern: Ticked
Generate data versioning and concurrency management: Ticked
and in the schema objects tab, select the schema objects you are interested in generating code for

Step 4 - Generate the business objects

Click on the 'Business Objects' tab to generate the domain objects and structures and relationships. Select the business objects you are interested in generating code for

Step 5 - Shoot!

Click on the 'Generate Code' button to generate the required code.

Because in this tutorial we selected the 'Generate data versioning and concurrency management' advanced option, the wizard may generate a script and prompt you to run that script against your database.
This script will create the _ctVersion column on your chosen table(s), which CodeTrigger uses to manage concurrency issues.

The test below tests the concurrency aspect (causes an expected concurrency failure). However if you do not wish to add this column to your database tables, you can uncheck the concurrency option above, and regenerate the code. However you will need to rewrite the test below to evaluate some other apect of the expected behaviour.


Step 6 - Create a new test client project using Visual Studio 2013-2017

Within the same Visual Studio solution, create a new 'Test' client project at an accessible location on your local hard drive. For the purposes of this sample, we will assume the following project settings:

Project Name: SampleRepositoryPattern.Tests
Project Default Namespace: SampleRepositoryPattern.Tests
Project Location: C:\CodeTriggerSamples\SampleRepositoryPattern\

In this test client project, if Visual studio has not generated an App.config file for you, you may have to add it yourself, via 'visual studio->add->new item->general->application configuration file' context menu items
Right click on the solution in Visual studio and 'Build Solution', ensure all the Visual Studio generated projects and code in the solution builds successfully.

Step 7 - Configure a test & RUN!

Now we create a basic test to demonstrate the usage of the generated code (repository pattern).
Note that this is not a tutorial on writing Unit tests! In particular, to keep things short we have put a lot of tests into the same test function which you certainly should not do when writing your own unit tests.

In the SampleRepositoryPattern.Tests project you created in step 5, add a reference to the SampleRepositoryPattern.Business project.
In the SampleRepositoryPattern.Data project folder you will also find a 'generated.config' file [C:\CodeTriggerSamples\SampleRepositoryPattern\SampleRepositoryPattern.Data\generated.config]
that contains additional configuration information for your application, including database connection information.
Copy the appSettings section in this file to the config section in your SampleRepositoryPattern.Tests project config file (App.config).

Thats it, you are ready to consume the business and data layer via your repository pattern.
In the UnitTest1 class that was generated by Visual Studio, add the following using namespace declarations:

using SampleRepositoryPattern.Business;
using SampleRepositoryPattern.Business.Interfaces;
using SampleRepositoryPattern.Business.Repository;
using SampleRepositoryPattern.Business.Repository.Interfaces;

You can then prep your business layer objects with the required repository like so:

var repoFactory = RF.New();
ICategoriesRepository iDAOCategoriesRepository = (ICategoriesRepository)repoFactory.CategoriesRepository;
BOCategories boCategory = new BOCategories();
boCategory.CategoriesRepository = iDAOCategoriesRepository;

The code below shows a test which:
  • creates and saves a new category object
  • gets the identity id issued by the database
  • checks that the version of the object in the db is 0
  • updates the object and saves to the db
  • checks that the version in the db has incremented to 1
  • deletes the object
  • checks that the object can no longer be instantiated/initialized
Of course each one of these items would normally be a test in itself, we are just presenting them together in this one big test to simplify this tutorial.
And thats it, you have successfully created and unit tested a multi-tier, database enabled, repository pattern based application with concurrency and versioning features built in, using CodeTrigger.

    using System;
    using System.Text;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using SampleRepositoryPattern.Business;
    using SampleRepositoryPattern.Business.Interfaces;
    using SampleRepositoryPattern.Business.Repository;
    using SampleRepositoryPattern.Business.Repository.Interfaces;
    namespace SampleRepositoryPattern.Tests
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void create_update_delete_Category()
            {
                string initialName = "My Test Category";
                string initialDescription = "initial desc";
                string updatedDescription = "updated desc";
                                
                //setup the test using a repository
                var repoFactory = RF.New();
                ICategoriesRepository iDAOCategoriesRepository = (ICategoriesRepository)repoFactory.CategoriesRepository;
                BOCategories boCategory = new BOCategories();
                boCategory.CategoriesRepository = iDAOCategoriesRepository;
                                
                try
                {
                    //test saving a new category
                    boCategory.CategoryName = initialName;
                    boCategory.Description = initialDescription;
                    boCategory.SaveNew();
                                    
                    //test#1 that the versioning is working properly, here the version should be 0 when we load 
                    int categoryID = (int)boCategory.CategoryID;
                    boCategory.Init(categoryID);
                    Assert.AreEqual(boCategory.CtrVersion, 0);
                                    
                    //test updating an existing category
                    boCategory.Description = updatedDescription;
                    boCategory.Update();
                    boCategory.Init(categoryID);
                    Assert.AreEqual(boCategory.Description, updatedDescription);
                                    
                    //test#2 that the concurrency & versioning is working properly, here the incremented version should be 1 
                    //after the previous update 
                    Assert.AreEqual(boCategory.CtrVersion, 1);
                                    
                    //test that we can delete
                    boCategory.Delete();
                                    
                    try
                    {
                        boCategory.Init(categoryID);
                        Assert.Fail("Test failed, object has been deleted and should no longer exist");
                    }
                    catch (Exception ex)
                    {
                        //test passed because we are expecting this exception as we are trying to initialise 
                        //with an id belonging to an object that no longer exists (since we deleted it above)
                        StringAssert.Contains(ex.Message, "Object reference");
                    }
                }
                catch
                {
                    //catch all to try and get rid of this test category so we can run this test again
                    boCategory.Delete();
                }
            }
        }
    }