TestValueFactory C# & Mapper Tests

When you’re writing tests, especially mapper tests, knowing the value which is mapped is not of great use. What you’re testing is that the value is correctly mapped, or bound to the accurate location in destination.

Mapping is very often not considered by young developer (and sometimes senior developer) as a source of error. In my opinion, actually it is. Thus, that’s why I am sharing those code snippets to help people writing tests on mappers.

Keep this sentence in mind, when writing tests in group code project : “Backup your a** !”. Everything can be a source of error.

The TestValueHelper implementation provide issue resolution to handle random type value generation. This class is certainly to be developped.

using System;
using System.Collections.Generic;

namespace maximilienzakowski.com.TestToolKit
{
    public static class TestValueFactory
    {
        private static readonly Random _random = new Random();

        public static int GetRandomIntValue()
        {
            return _random.Next();
        }

        public static int GetRandomIntValue(int minValue, int maxValue)
        {
            return _random.Next(minValue, maxValue);
        }

        public static int GetRandomIntValue(int[] except)
        {
            var exceptSet = new HashSet<int>(except??new int[] { });
            int result;
            do
            {
                result = _random.Next();
            }
            while (exceptSet.Contains(result));
            return result;
        }

        public static DateTime GetRandomDateTimeValue()
        {
            DateTime start = new DateTime(1970, 1, 1);
            int range = (DateTime.Today - start).Days;
            return start.AddDays(_random.Next(range))
                .AddHours(_random.Next(0, 24))
                .AddMinutes(_random.Next(0, 60))
                .AddSeconds(_random.Next(0, 60));
        }

        public static double GetRandomDoubleValue()
        {
            return _random.Next() * _random.NextDouble();
        }

        public static decimal GetRandomDecimalValue()
        {
            double RandH, RandL;
            do
            {
                RandH = _random.NextDouble();
                RandL = _random.NextDouble();
            } while ((RandH > 0.99999999999999d) || (RandL > 0.99999999999999d));
            return (decimal)RandH + (decimal)RandL / 1E14m;
        }
        public static decimal GetRandomDecimalValue( decimal minValue, decimal maxValue)
        {
            return GetRandomDecimalValue() * (maxValue - minValue) + minValue;
        }

        public static T GetRandomEnumValue<T>() where T : System.Enum
        {
            var values = Enum.GetValues(typeof(T));
            return (T)values.GetValue(_random.Next(0,values.Length-1));
        }

        public static string GetRandomStringValue()
        {
            return GetRandomStringValue(20);
        }

        public static string GetRandomStringValue(int length)
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            return new string(Enumerable.Repeat(chars, length).Select(s => s[_random.Next(s.Length)]).ToArray());
        }
    }
}

Tested code snippet which is a builder + mapper association :

public class ItemToInvoiceRowConverter2
    {
        public IInvoiceRow Convert(IItem converted)
        {
            if (converted == null) return null;
            var result = new InvoiceRow();
            //result.Number = converted.Id;
            result.IdItem = converted.Id;
            result.Kind = converted.Kind;
            result.Label = converted.Name;
            //result.Vat = converted.;
            result.Unit = converted.Unit;
            result.UnitPrice = converted.Price;
            //result.Discount = converted.Id;
            //result.Quantity = converted.Id;
            return result;
        }
    }

Unit test code :

using myApplication.Converters;
using myApplication.Models;
using maximilienzakowski.com.TestToolKit;
using Moq;
using NUnit.Framework;

namespace myApplication.Tests
{
    [TestFixture]
    public class ItemToInvoiceRowConverterTests
    {
        private ItemToInvoiceRowConverter2 BuildTested()
        {
            return new ItemToInvoiceRowConverter2();
        }

        [Test]
        public void ConvertShouldReturnNullWhenConvertedIsNull()
        {
            var tested = BuildTested();
            var result = tested.Convert(null);
            Assert.IsNull(result);
        }


        [Test]
        public void ConvertShouldConvertAndMapAccurately()
        {
            var converted = new Mock<IItem>();
            var id = TestValueFactory.GetRandomIntValue();
            var kind = TestValueFactory.GetRandomStringValue();
            var name = TestValueFactory.GetRandomStringValue();
            var unit = TestValueFactory.GetRandomStringValue();
            var price = TestValueFactory.GetRandomDecimalValue();

            converted.SetupGet(x => x.Id).Returns(id);
            converted.SetupGet(x => x.Kind).Returns(kind);
            converted.SetupGet(x => x.Name).Returns(name);
            converted.SetupGet(x => x.Unit).Returns(unit);
            converted.SetupGet(x => x.Price).Returns(price);
            var tested = BuildTested();
            var result = tested.Convert(converted.Object);
            Assert.IsNotNull(result);
            Assert.AreEqual(id, result.IdItem);
            Assert.AreEqual(kind, result.Kind);
            Assert.AreEqual(name, result.Label);
            Assert.AreEqual(unit, result.Unit);
            Assert.AreEqual(price, result.UnitPrice);

            converted.VerifyGet(x => x.Id,Times.Once);
            converted.VerifyGet(x => x.Kind, Times.Once);
            converted.VerifyGet(x => x.Name, Times.Once);
            converted.VerifyGet(x => x.Unit, Times.Once);
            converted.VerifyGet(x => x.Price, Times.Once);
            converted.VerifyNoOtherCalls();
        }
    }
}

Hope this will help someone else than me…

Linq.Net To SqlLite Converter implementation attempt

Sometimes when you want to manage your code efficiency you may need to optimize some .Net implementation.

Instead of relying on Entity Framework or other closed binary implementation you may need to implement your specific AdHoc behavior, this is a good example to do so…

Underneath you will find my proposal to implement a Linq to SQLLite conversion with C#. This is a generic code and may be optimized in many way for your implementation needs. It use System.Linq but remediation can be done very easily to not depend on this library.

using System.Collections;
using System.Linq.Expressions;
using System.Reflection;

namespace Com.Maximilienzakowski.Dal.Common.Repository
{
    public interface ICommandTextWhereArgBuilder<T> where T : class
    {
        string Build(Expression<Func<T, bool>> whereExpression);
        string Build(Expression node);
    }

    public class SqliteCommandTextWhereArgBuilder<T> : ICommandTextWhereArgBuilder<T> where T : class
    {
        private readonly IDictionary<ExpressionType,ISqlLiteWhereCommandExpressionBuilder> _whereExpressionsBuilders;
        private readonly IObjectToSqlValueConverter _objectToSqlValueConverter = new ObjectToSqlValueConverter();
        public SqliteCommandTextWhereArgBuilder()
        {
            var sqlLiteWhereCommandExpressionBuilders = new ISqlLiteWhereCommandExpressionBuilder[]
            {
                new SqlLiteLambdaWhereCommandExpressionBuilder<T>(this),
                new SqlLiteAndWhereCommandExpressionBuilder<T>(this),
                new SqlLiteAndAlsoWhereCommandExpressionBuilder<T>(this),
                new SqlLiteEqualWhereCommandExpressionBuilder<T>(this),
                new SqlLiteContainsCallWhereCommandExpressionBuilder<T>(this),
                new SqliteConvertAccessWhereCommandExpressionBuilder<T>(this),
                new SqliteMemberAccessWhereCommandExpressionBuilder<T>(_objectToSqlValueConverter),
                new SqliteConstantWhereCommandExpressionBuilder<T>(_objectToSqlValueConverter),
                
            };
            _whereExpressionsBuilders = sqlLiteWhereCommandExpressionBuilders.ToDictionary(m => m.ExpressionType, m => m);
        }


        public string Build(Expression<Func<T, bool>> whereExpression)
        {
            var expression = whereExpression.Reduce;
            return Build(expression());
        }

        public string Build(Expression node)
        {
            if(!_whereExpressionsBuilders.TryGetValue(node.NodeType, out var whereExpressionBuilder)) return "UNDEFINED EXPRESSION BUILDER";
            return whereExpressionBuilder.Build(node);
        }
    }

    public class SqlLiteContainsCallWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;
        public ExpressionType ExpressionType => ExpressionType.Call;
        public SqlLiteContainsCallWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }
        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType.Call) return string.Empty;
            var methodCallNode = (MethodCallExpression)node;
            if (methodCallNode.Method.Name != "Contains") return "UNHANDLED METHOD CALL";
            if(methodCallNode.Arguments.Count == 2)
            {
                return $"({ _commandTextWhereArgBuilder.Build(methodCallNode.Arguments.Last())} IN {_commandTextWhereArgBuilder.Build(methodCallNode.Arguments.First())})";
            }
            else if(methodCallNode.Arguments.Count == 1)
            {
                var left = _commandTextWhereArgBuilder.Build(methodCallNode.Arguments.Single());
                return $"({left} IN {_commandTextWhereArgBuilder.Build(methodCallNode.Object)})";
            }
            return "UNHANDLED CONTAINS METHOD CALL";
        }
    }


    public class SqlLiteLambdaWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;
        public ExpressionType ExpressionType => ExpressionType.Lambda;
        public SqlLiteLambdaWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }
        public string Build(Expression? node)
        {
            if(node.NodeType != ExpressionType.Lambda) return string.Empty;
            var lambdaNode = (LambdaExpression)node;
            return _commandTextWhereArgBuilder.Build(lambdaNode.Body);
        }
    }

    public class SqlLiteAndWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;

        public ExpressionType ExpressionType => ExpressionType.And;
        public SqlLiteAndWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var binaryExpressionType = (BinaryExpression)node;
            return $"({_commandTextWhereArgBuilder.Build(binaryExpressionType.Left)}) AND ({_commandTextWhereArgBuilder.Build(binaryExpressionType.Right)})";
        }
    }

    public class SqlLiteAndAlsoWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;

        public ExpressionType ExpressionType => ExpressionType.AndAlso;
        public SqlLiteAndAlsoWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var binaryExpressionType = (BinaryExpression)node;
            return $"({_commandTextWhereArgBuilder.Build(binaryExpressionType.Left)}) AND ({_commandTextWhereArgBuilder.Build(binaryExpressionType.Right)})";
        }
    }

    public class SqlLiteEqualWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;

        public ExpressionType ExpressionType => ExpressionType.Equal;
        public SqlLiteEqualWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var binaryExpressionType = (BinaryExpression)node;
            return $"{_commandTextWhereArgBuilder.Build(binaryExpressionType.Left)} = {_commandTextWhereArgBuilder.Build(binaryExpressionType.Right)}";
        }
    }

    public class SqliteMemberAccessWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {

        private readonly IObjectToSqlValueConverter _objectToSqlValueConverter;
        public ExpressionType ExpressionType => ExpressionType.MemberAccess;
        public SqliteMemberAccessWhereCommandExpressionBuilder(IObjectToSqlValueConverter objectToSqlValueConverter)
        {
            _objectToSqlValueConverter = objectToSqlValueConverter ?? throw new ArgumentNullException(nameof(objectToSqlValueConverter));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var memberExpression = (MemberExpression)node;
            if(memberExpression.Member.MemberType == MemberTypes.Field)
            {
                if(memberExpression.Expression == null) return "NULL UNDERLYING EXPRESSION IN MEMBER EXPRESSION";
                if (memberExpression.Expression.NodeType != ExpressionType.Constant) return "NOT A CONSTANT EXPRESSION NODE TYPE IN MEMBER EXPRESSION";
                var constantExpression = (ConstantExpression)memberExpression.Expression;
                var fieldInfo = (FieldInfo)memberExpression.Member;
                return $"\"{_objectToSqlValueConverter.Convert(fieldInfo.GetValue(constantExpression.Value))}\"";
            }
            return $"\"{memberExpression?.Member?.Name}\"";
        }
    }

    public class SqliteConvertAccessWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {

        private readonly ICommandTextWhereArgBuilder<T> _commandTextWhereArgBuilder;
        public ExpressionType ExpressionType => ExpressionType.Convert;
        public SqliteConvertAccessWhereCommandExpressionBuilder(ICommandTextWhereArgBuilder<T> commandTextWhereArgBuilder)
        {
            _commandTextWhereArgBuilder = commandTextWhereArgBuilder ?? throw new ArgumentNullException(nameof(commandTextWhereArgBuilder));
        }

        private static readonly IDictionary<Tuple<Type, Type>, string> _formatBySourceAndDestinationTupleTypes =
            new Dictionary<Tuple<Type, Type>, string>()
            {
                {Tuple.Create(typeof(int),typeof(long)), "{0}" },
            };

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var unaryExpression = (UnaryExpression)node;
            if (!_formatBySourceAndDestinationTupleTypes.TryGetValue(Tuple.Create(unaryExpression.Operand.Type, unaryExpression.Type), out var format))
                return "UNKNONW CONVERT EXPRESSION";
            return string.Format(format, _commandTextWhereArgBuilder.Build(unaryExpression.Operand));
        }
    }

    public class SqliteConstantWhereCommandExpressionBuilder<T> : ISqlLiteWhereCommandExpressionBuilder where T : class
    {
        private readonly IObjectToSqlValueConverter _objectToSqlValueConverter1;
        public ExpressionType ExpressionType => ExpressionType.Constant;
        public SqliteConstantWhereCommandExpressionBuilder(IObjectToSqlValueConverter objectToSalValueConverter)
        {
            _objectToSqlValueConverter1 = objectToSalValueConverter ?? throw new ArgumentNullException(nameof(objectToSalValueConverter));
        }

        public string Build(Expression? node)
        {
            if (node.NodeType != ExpressionType) return string.Empty;
            var constantExpression = (ConstantExpression)node;
            return _objectToSqlValueConverter1.Convert(constantExpression.Value);
        }
    }

    


    public class ObjectToSqlValueConverter : IObjectToSqlValueConverter
    {
        private readonly IDictionary<Type, Func<object, string>> _valueConversionFuncByType =
            new Dictionary<Type, Func<object, string>>()
            {
                {typeof(string), value => $"'{value}'"},
                {typeof(int), value => $"{value}"},
                {typeof(long), value => $"{value}"},
                {typeof(short), value => $"{value}"},
                {typeof(float), value => $"{value}"},
                {typeof(double), value => $"{value}"},
                {typeof(decimal), value => $"{value}"},
            };
        public string Convert(object? value)
        {
            if (value == null) return "NULL";
            var valueType = value.GetType();
            if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                var underlyingValueType = Nullable.GetUnderlyingType(valueType);
                if (underlyingValueType == null) return "UNKNOWN CASE OF NULLABLE UNDERLYING NULL VALUE";
                return Convert(System.Convert.ChangeType(value, underlyingValueType));
            }
            if((valueType.IsArray || valueType.IsGenericType && valueType.GetGenericTypeDefinition().IsAssignableTo(typeof(IEnumerable))))
            {
                var enumerable = (IEnumerable)value;
                return $"({string.Join(",", Enumerate(enumerable).Select(Convert))})";
            }
            if (!_valueConversionFuncByType.TryGetValue(valueType, out var conversionFunc)) return "UNKNOWN TYPE";
            return conversionFunc(value);
        }

        private IEnumerable<object> Enumerate(IEnumerable enumerable)
        {
            foreach(var value in enumerable)
            {
                yield return value;
            }
        }
    }
}

2016 -> 2017 La Française AM (Quant support & NoSQL Data migration)

Marklogic Integrator (Big Data – NoSQL) and Matlab/C#/Java Quant technical support

Risk database and workflow migration responsible

Employment Dates Feb. 2017 – Jul. 2017

Employment duration 12 month

Location Paris, France

Technical Achievements


– SQL Server 2014 (OLAP and OLTP association) vs Marklogic benchmark
– Stored procedure and pipeline processing workflow integration (XPath, T-SQL)
– Marklogic bi-temporality integration, alerting, pipelines features integration
– Big Data management steps integration :
–> data Ingestion : HTTP Web-dav protocol, MLCP
–> pre-control : Custom Excel parametric content validator integration
–> processing : transformation routine integration (XQuery -> Functional implementation)
–> post-control : XML/XSD design and ruleset integration
–> persistence : instance identity definition and persistence integrity management (XQuery -> Functional implementation)
– Data Exposition with ODBC interface server and Rest Services
– Process installation tools development (Powershell, Roxy, Ruby, REST)
– Data driven development :
–> Data consistency tests designing, integration and automation (Data driven development)
–> Integration/Processing performance testing
– Related BI programs tools benchmarking (QlikView, PowerBI,Tableau)


Management tasks

– Standup meeting organization (Agile)
– Milestone meeting organization, demonstration and presentation (Weekly) (Agile)
– Coordination with system administration for delivery purposes and hardware sizing
– Coordination of the offshores development teammates (communication with Serbia – MS Line)
– Technical and teaching support to Risk service on Marklogic, XQuery, XSD, XSLT, Javascript, JSON…voir plus

Integration of insurance financial products market stress testing simulator (Solvency II and derivates legislation) (massive computation).


Analysis tasks

– AIOPA Solvency II legislation rulesets analysis
– Customer needs analysis and computation model conceptualization

Quant support


– Excel requested GUI dashboard integration and interfacing (VBA, Matlab XLLink)
– Datasource interfacing and retrieved data correction workflow setup (C#, Matlab, COM)
– Custom inversion control Matlab architecture integration (Matlab, Java)
– Stress application (Vol shocking, Rate shocking …)
– Pricing engine interfacing, computation orchestration (Matlab 2016 R2)
– Simulation result database design and integration (SQL Server 2014)
– Matlab/Sql Server interfacing (Matlab, ADO.Net and Matlab Database, ODBC)
– Matlab process logging routine integration with log4j integration (not logm)
– Remote console listener implementation for monitoring purposes (Java, Swing)
– Database report result extraction tools implementation (SQL Server, C# 4, Excel Interop framework)
– Test Driven Development (TDD) and Data Driven Development
– Performance optimization with Matlab vectorization and functional programmation rules
– Multiserver computation with Matlab Parallel extension (Parpool and DHCP) -> custom serialization management
– Technical documentation writing
– Black Scholes diffusion computation optimization with Graphic Cards (Nvidia CUDA 8.0, Tesla and GTX 680)

Solution commissioning
– Data and result validation
– Performance tuning and monitoring

Others
– TFS source control tools introduction
– Continuous delivery introduction with related job setup (Gated checkins, builds, testing and delivery)

PinkFlower.fr

Pinkflower.fr is a website of a massage parlour which aims to get persons rid of stress and improve their well beings. They propose a large range of massage which are all of great quality.

This massage parlour is located in Plessis-Bouchard (Postal code : 95130), France

I helped in this project to :

  • Design the website
  • Setup the website
  • Choose and setup scheduling functionality
  • Setup the galleries
  • Setup SEO (Search Engine Optimization) in order to have the website well referenced.

You can visit the website at : https://www.pinkflower.fr/

Pinkflower main page

Energia – Analiza – Urządzenia

I actively collaborated with Tomasz SZYMANSKI in order to help him to set up his website.

This website give you advise, definitions and propose you devices in order to measure and benefit from different kind of energy advantages.

Website url : https://energia-orgonu.com/

Screen shot of the Energia – Analyza – Urządzenia website.

2012 -> 2013 – CNC -Intranet platform development

CNC – From August 2012 until September 2013

CNC (Centre National de la cinématographie) is a French organisation which deals with French cinema administration

This works consisted in designing, programming and installing an intranet website for the CNC

The intranet technical architecture was composed with three part :

  • SQL Server database
  • Web Service Layer
  • Internet server client which query the web service and provide internet HTML (internet) content for light client

2013 -> 2016 – SG – Commando Developer

Commando Developer (VBA, Python, C++) – Revenue Cash Reinvestment desk support

EmploymeNt Dates sept. 2013 – avr. 2016

Employment Duration 2 ans 8 mois

LOCATION Paris , France

Support and implementation of new program’s functionalities in commando style development (very-fast development) alloying the reinvestment of the cash generated by security lending activities.

Achieved activities :

Functional achievements :
– Achievement of an automatic cash allocation tools for cash distribution with target allocation ratios in Mutual-Funds.
– Programming and improvement of Profit and Lost reporting tools (Performance improvement, new reporting methods setting up…)
– Back office flow achievement and management (Position movement, Cash movement, Security movement, Performance…)
– Monitoring and support activities
– Assistance and retro-engineering of the achieved scripts in commando style

Technical achievement :
– Performance improvement in order to cope with volumes increase with ordered and treated deals (achievement of ACID interfacing between achieved software and database). ADODB Framework
– VBA routines Writing / Re-Writing
– Performance critical VBA script to C++ rewriting
– Applicative migration from VBA Access to MS .NET
– VBA Software adaptation in order to migrate it from Windows XP to Windows 7

Transverse achievement :
– Jython’s DLL writing (Python compiled in Java ByteCode) in order to integrate VBA commando written script in Reuters Kondor K+ package software.

Welder cart project

When you buy a welder, very often the welder does not come with it’s own support cart. Very often your first welding project can be to weld your own carret.

Inspirate yourself

In order to build a cart you should know what are the primary and asides functionalities that the cart should propose. Google Shopping or Bing Shopping are a good source of information.

Another thing to check is the welder manufacturer proposals.

In my case this was the proposal of the manufacturer…

Do not reinvente everything, choose a good basis…

I had to find a good basis, in my case that was a dolly truck.

Diable rigide HAILO, charge garantie 150 kg | Leroy Merlin

Generally the point that you have to check with such products are the price and the presence of the a majority og the component that you need for your project. Entry-level product which are at the same time call product gather those properties.

Check your solution viability

Another thing to check is to check if there is no cheapest solution than the general cost of my project. If the cheapest solution respond to your quality expectation there is no reason to involve into this project and go buy the solution.

Design time

Create a CAD design of your project that report every measurement of the project. Take care of the simplicity of the solution/cart. Complexe stuff are generally expensive to build.

My carret CAD design

The result

After multiple iteration cycle at the end the cart is like this…

Two used dolly truck and one metal sheet.

Missing enhancement :

  • Alimentation cable reel.
  • Welding attachment strap
  • other stuff…

Beware ! The trap here, as you have the power to enhance your trolley is to make a thing that is over complicated. Keep that in mind : Keep it simple as possible !

Database Template Handler Project

As the ORMs (Object Relational Model) are now very used in the computer development project in order to manage interfacing between systems, the DB Template Handler project is an atempt to solve the issue of the heterogeneity between languages that you interface in your data access layout.

The Project try to create a devoted semantic and language basic functionality to manage the generation of every file suitable to database or other DAL interfacing.

Image

The project page :

https://github.com/cosXsinX/DBTemplateHanlder-NetCore3

Jointure implementation in C#

Sometimes when you want to manage your code efficiency you may need to optimize some .Net implementation.

Jointure implementation in C# may be such a case.

Underneath you will find my proposal to implement a jointure in C# environment. This is a generic code and may be optimized in many way for your implementation needs. It use System.Linq but remediation can be done very easily to not depend on this library.

using System;
using System.Collections.Generic;
using System.Linq;

namespace org.maximilienzakowski.Jointures
{
    public static class Extensions
    {
        public static TJ[] InnerJoin<TL, TR, TK, TJ>(this IEnumerable<TL> lefts, IEnumerable<TR> rights, Func<TL, TK> onLeftKey, Func<TR, TK> onRightKey,
           Func<TL, TR, TJ> jointureBuilder)
        {
            var leftsWithKeys = lefts.Select(l => new Tuple<TL, TK>(l, onLeftKey(l)));
            var rightsWithKeys = rights.Select(r => new Tuple<TR, TK>(r, onRightKey(r)));
            var rightGroupsByKey = rightsWithKeys.GroupBy(r => r.Item2, m => m.Item1).ToDictionary(m => m.Key, m => m.ToArray());
            var defaultJoineds = new TR[] { };
            var enumerable = leftsWithKeys.SelectMany(m =>
            {
                TR[] joineds = defaultJoineds;
                if (m.Item2 != null)
                {
                    rightGroupsByKey.TryGetValue(m.Item2, out joineds);
                }
                return (joineds ?? defaultJoineds).Select(joined => jointureBuilder(m.Item1, joined));
            });
            return enumerable.ToArray();
        }
        public static Tuple<TL,TR>[] LeftJoin<TL,TR,TK>(this IEnumerable<TL> lefts, IEnumerable<TR> rights, Func<TL,TK> onLeftKey, Func<TR,TK> onRightKey)
        {
            return LeftJoin(lefts, rights, onLeftKey, onRightKey, (left, right) => new Tuple<TL, TR>(left, right), default(TR));
        }

        public static Tuple<TL,TR>[] LeftJoin<TL,TR,TK>(this IEnumerable<TL> lefts, IEnumerable<TR> rights,
            Func<TL,TK> onLeftKey, Func<TR,TK> onRightKey,TR defaultJoined)
        {
            return LeftJoin(lefts, rights, onLeftKey, onRightKey, (left, right) => new Tuple<TL, TR>(left, right), defaultJoined);
        }

        public static IList<TJ> LeftJoin<TL,TR,TK,TJ>(this IEnumerable<TL> lefts,IEnumerable<TR> rights, Func<TL,TK> onLeftKey,Func<TR,TK> onRightKey, Func<TL,TR,TJ> jointureBuilder)
        {
            return LeftJoin(lefts, rights, onLeftKey, onRightKey, jointureBuilder, default(TR));
        }

        public static TJ[] LeftJoin<TL,TR,TK,TJ>(this IEnumerable<TL> lefts, IEnumerable<TR> rights, Func<TL,TK> onLeftKey,Func<TR,TK> onRightKey, 
            Func<TL,TR,TJ> jointureBuilder, TR defaultJoined)
        {
            var leftsWithKeys = lefts.Select(l => new Tuple<TL, TK>(l, onLeftKey(l)));
            var rightsWithKeys = rights.Select(r => new Tuple<TR, TK>(r, onRightKey(r)));
            var rightGroupsByKey = rightsWithKeys.GroupBy(r => r.Item2, m => m.Item1).ToDictionary(m => m.Key, m => m.ToArray());
            var defaultJoineds = new TR[] { defaultJoined };
            var enumerable = leftsWithKeys.SelectMany(m =>
            {
                TR[] joineds = defaultJoineds;
                if(m.Item2 != null)
                {
                    rightGroupsByKey.TryGetValue(m.Item2, out joineds);
                }
                return (joineds ?? defaultJoineds).Select(joined => jointureBuilder(m.Item1, joined));
            });
            return enumerable.ToArray();
        }


        public static Tuple<TL,TR>[] FullJoin<TL,TR,TK>(this IEnumerable<TL> lefts, IList<TR> rights,
            Func<TL,TK> leftKeyFunc, Func<TR,TK> rightKeyFunc, TL defaultLeft = default(TL), TR defaultRight = default(TR))
        {
            var leftJoinedToRight =
                lefts.LeftJoin(rights, leftKeyFunc, rightKeyFunc, defaultRight).ToArray();
            var joinedRightKeys =
                new HashSet<TK>(leftJoinedToRight
                    .Where(m => m.Item2 != null)
                    .Select(m => rightKeyFunc(m.Item2)).Distinct());
            var defaultLeftAndMissingRights =
                rights
                    .Select(m => Tuple.Create(m, rightKeyFunc(m)))
                    .Where(m => !joinedRightKeys.Contains(m.Item2))
                    .Select(m => Tuple.Create(defaultLeft, m.Item1)).ToArray();
            var fullJointure = leftJoinedToRight.Concat(defaultLeftAndMissingRights).ToArray();
            return fullJointure;
        }
    }
}