Comments Todo And Hack In C

 

Hello everybody,

today I want to leave one more note, which you can use for boosting your productivity.

Imagine following scenario. On the meeting with customer you've got some list of to do points. You have them on your email. You've made some research, and found that you need to make changes to 5 C# files. How not to forget about all of those files?

On rescue comes two comments in C#:

  1. TODO
  2. HACK

Leave those comments in your 5 files -> save all files -> Open Task List, and you'll see something like this:

As you can see from presented screenshot, after you leave TODO or HACK comments in 5 C# files, you'll be in perfect position of usage of code.

What is even more interesting, with help of double click you can navigate to exact comment location.

 

Three States Of Fields In Acumatica

 

Hello everybody,

today I want to write a short note on three states of fields existing in Acumatica:

  1. Exists but is empty
  2. Exist and have value
  3. Has null

If to speak about string, it can exist like this:

  1.  
  2. Some value
  3.  

Do you see difference between 1 and 3? Not easy. As usually developers of C#, show this difference like this:

  1. ""
  2. "Some Value"
  3. null

And following screenshot with explanation shows how it works in case of SOAP contracts:

 so, while you make integration, keep that in mind

 

Strong Name Validation By Pass

 

Hello,

here I want to leave a short notice how to manage strong name validation in Windows. For this purpose you can manage via following keys in regedit:

To enable the strong-name bypass feature for all applications: switch the value for AllowStrongNameBypass to 1 in
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework keys

With those changes you'll get your validation turn off. If you want to set it on, then set AllowStrongNameBypass to 0

No Comments

 

Add a Comment
 

 

Entity Framework One To Many Relationship

 

Hello everybody,

today I want to make short post on how to confiugre one to many relationship in Entity Framework 6.

Imagine following: One group can have multiple students. So one to many relationship. For this purpose you can use following convention configuration agreement:

public class Student
{
    public int StudentId { getset; }
    public string StudentName { getset; }
}
 
public class Group
{
    public int GroupId { getset; }
    public string GroupName { getset; }
    public string Department { getset; }
 
    public List<Student> Students { getset; }
}

In presented example class group includes navigation property Students. 

Another convention is like this:

public class Student
{
    public int StudentId { getset; }
    public string StudentName { getset; }
 
    public Group CurrentGroup { getset; }
}
 
public class Group
{
    public int GroupId { getset; }
    public string GroupName { getset; }
    public string Department { getset; }
 
    public List<Student> Students { getset; }
}

as you can see, difference is that Student instance by itself knows to which Group it belongs. 

No Comments

Add a Comment
 

 

Invokeifrequired Template

 

Hello everybody,

today I want to document simple but very useful feature if you work with multiple threads in Winforms application. 

Quite often it happens that you execute in some paralel thread long running calculations and would like time from the time notify results to UI. 

But if you try to do this then you'll get an error that will say to you that parallel thread doesn't have permissions to some control because it didn't create such a control. So, how then update UI?

The answer is simple, you should use method Invoke of the control. In that case everything inside of method Invoke will be executed from UI thread. 

Needless to say that such approach is workable but to some degree cumbersome. So in order to simplify life I've created following extension method:

public static class Extensions
{
    public static void InvokeIfRequired(this ISynchronizeInvoke obj, MethodInvoker action)
    {
        if (obj.InvokeRequired)
        {
            var args = new object[0];
            obj.Invoke(action, args);
        }
        else
        {
            action();
        }
    }
}

And then in order to update text box field following logic was enough:

txtLog.InvokeIfRequired(() =>
{
    txtLog.Text += "\r\n check following id SubAccount: " + foundItem.RowId;
});

No Comments

Add a Comment
 

 

Acumatica Dac Class Generator

 

Hello everyboydy,


today I want to share with anybody mine implementation of DAC class generator.

By default Acumatica provides you with DAC class generator which is pretty good.

But time from the time I had a need to generate DAC class into text field, and then

put it somewhere in my solution, and Acumatica DAC class generator didn't feet to

mine needs. So I decided to create my own DAC class generator. 

This form has simple interface. In the first line you enter Connection string, at second



line you enter table name, press at generate, and receive DAC class.

You can download source code here

Below goes also some C# code which I've comment later:

    public static string FirstCharToUpper(string input)
    {
        if (String.IsNullOrEmpty(input))
            throw new ArgumentException("ARGH!");
        return input.First().ToString().ToUpper() + String.Join("", input.Skip(1));
    }
 
    public static string FirstCharToLower(string input)
    {
        if (String.IsNullOrEmpty(input))
            throw new ArgumentException("ARGH!");
        return input.First().ToString().ToLower() + String.Join("", input.Skip(1));
    }
 
    private void btnGenerate_Click(object sender, EventArgs e)
    {
        string cSharp = "[Serializable]\r\n";
        cSharp += $"public class {txtTableName.Text} : IBqlTable \r\n        {{";
 
        var columnNames = GetColumnsNames(txtTableName.Text);
 
        foreach (var column in columnNames)
        {
            string abstractClassName = FirstCharToLower(column.ColumnName);
            string memberFieldName = FirstCharToUpper(column.ColumnName);
            string propertyName = "_" + memberFieldName;
            string caption = SplitCamelCase(memberFieldName);
 
            if (column.ColumnType == "int")
            {
                string intImplementation =
                    $"\r\n        #region {memberFieldName}\r\n        public abstract class {abstractClassName} : IBqlField\r\n        {{\r\n        }}\r\n\r\n        " +
                    $"[PXDBInt()]\r\n        [PXUIField(DisplayName = \"{caption}\", " +
                    $"Visibility = PXUIVisibility.Visible, Visible = false, Enabled = false)]\r\n        " +
                    $"public virtual int? {memberFieldName} {{ get; set; }}\r\n\r\n        #endregion\r\n";
                cSharp += intImplementation;
            }
            if (column.ColumnType == "nvarchar")
            {
                int length = column.MaximumLength.Value;
                string nvarcharImplementation =
                    $"\r\n         #region route\r\n        public abstract class {abstractClassName} : IBqlField\r\n        " +
                    $"{{\r\n        }}\r\n        [PXDBString({length})]\r\n        [PXUIField(DisplayName = \"{caption}\", Visibility = PXUIVisibility.Visible)]\r\n        " +
                    $"public virtual string {memberFieldName} {{ get; set; }}\r\n        #endregion\r\n";
                cSharp += nvarcharImplementation;
            }
            if (column.ColumnType == "decimal")
            {
                int length = column.NumericScalse.Value;
                string decimalImplementation =
                    $"\r\n        #region {memberFieldName}\r\n        public abstract class {abstractClassName} : IBqlField\r\n      " +
                    $"  {{\r\n        }}\r\n        [PXDBDecimal({length})]\r\n        [PXDefault(TypeCode.Decimal, \"0.0\")] \r\n        " +
                    $"[PXUIField(DisplayName = \"{caption}\", Visibility = PXUIVisibility.Visible)]\r\n      " +
                    $"  public virtual decimal? {memberFieldName} {{ get; set; }}\r\n        #endregion\r\n";
                cSharp += decimalImplementation;
            }
            if (column.ColumnType =="datetime")
            {
                string datetimeImplementation =
                    $"\r\n        #region {memberFieldName}\r\n        public abstract class {abstractClassName}  : IBqlField\r\n        " +
                    $"{{\r\n        }}\r\n        [PXDBDate()]\r\n        [PXUIField(DisplayName = \"{caption}\", " +
                    $"Visibility = PXUIVisibility.SelectorVisible)]\r\n        " +
                    $"public virtual DateTime? {memberFieldName} {{ get; set; }}\r\n        #endregion\r\n";
                cSharp += datetimeImplementation;
            }
        }
 
        string serviceFields =
            "        #region CreatedByID\r\n\t\tpublic abstract class createdByID : IBqlField\r\n\t\t{\r\n\t\t}\r\n\t\tprotected Guid? " +
            "_CreatedByID;\r\n\t\t[PXDBCreatedByID()]\r\n\t\tpublic virtual Guid? CreatedByID\r\n\t\t{\r\n\t\t\tget\r\n\t\t\t{\r\n\t\t\t\treturn " +
            "this._CreatedByID;\r\n\t\t\t}\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\tthis._CreatedByID = value;\r\n\t\t\t}\r\n\t\t}\r\n\t\t#endregion\r\n\t\t#region " +
            "CreatedByScreenID\r\n\t\tpublic abstract class createdByScreenID : " +
            "PX.Data." +
            "IBqlField\r\n\t\t{\r\n\t\t}\r\n\t\tprotected String _CreatedByScreenID;\r\n\t\t[PXDBCreatedByScreenID()]\r\n\t\tpublic virtual " +
            "String CreatedByScreenID\r\n\t\t{\r\n\t\t\tget\r\n\t\t\t{\r\n\t\t\t\treturn " +
            "this._CreatedByScreenID;\r\n\t\t\t}\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\tthis._CreatedByScreenID = value;\r\n\t\t\t}\r\n\t\t}\r\n\t\t" +
            "#endregion\r\n\t\t#region CreatedDateTime\r\n\t\tpublic abstract class createdDateTime : IBqlField\r\n\t\t{\r\n\t\t}\r\n\t\tprotected DateTime? " +
            "_CreatedDateTime;\r\n\t\t[PXDBCreatedDateTime()]\r\n\t\tpublic virtual DateTime? " +
            "CreatedDateTime\r\n\t\t{\r\n\t\t\tget\r\n\t\t\t{\r\n\t\t\t\treturn this._CreatedDateTime;\r\n\t\t\t}\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\tt" +
            "his._CreatedDateTime = value;\r\n\t\t\t}\r\n\t\t}\r\n\t\t#endregion\r\n\t\t#region LastModifiedByID\r\n\t\tpublic " +
            "abstract class lastModifiedByID : IBqlField\r\n\t\t{\r\n\t\t}\r\n\t\tprotected Guid? " +
            "_LastModifiedByID;\r\n\t\t[PXDBLastModifiedByID()]\r\n\t\tpublic virtual Guid? LastModifiedByID\r\n\t\t{\r\n\t\t\t" +
            "get\r\n\t\t\t{\r\n\t\t\t\treturn this._LastModifiedByID;\r\n\t\t\t}\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\t" +
            "this._LastModifiedByID = value;\r\n\t\t\t}\r\n\t\t}\r\n\t\t#endregion\r\n\t\t#region LastModifiedByScreenID\r\n\t\tpublic abstract class " +
            "lastModifiedByScreenID : PX.Data.IBqlField\r\n\t\t{\r\n\t\t}\r\n\t\tprotected String _LastModifiedByScreenID;\r\n\t\t" +
            "[PXDBLastModifiedByScreenID()]\r\n\t\tpublic virtual String LastModifiedByScreenID\r\n\t\t{\r\n\t\t\tget\r\n\t\t\t{\r\n\t\t\t\t" +
            "return this._LastModifiedByScreenID;\r\n\t\t\t}\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\tthis._LastModifiedByScreenID = " +
            "value;\r\n\t\t\t}\r\n\t\t}\r\n\t\t#endregion\r\n\t\t#region LastModifiedDateTime\r\n\t\tpublic abstract class lastModifiedDateTime : " +
            "IBqlField\r\n\t\t{\r\n\t\t}\r\n\t\tprotected DateTime? _LastModifiedDateTime;\r\n\t\t[PXDBLastModifiedDateTime()]\r\n\t\tpublic virtual DateTime? " +
            "LastModifiedDateTime\r\n\t\t{\r\n\t\t\tget\r\n\t\t\t{\r\n\t\t\t\treturn " +
            "this._LastModifiedDateTime;\r\n\t\t\t}\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\tthis._LastModifiedDateTime = value;" +
            "\r\n\t\t\t}\r\n\t\t}\r\n\t\t#endregion\r\n\t\t#region tstamp\r\n\t\tpublic abstract class Tstamp : " +
            "PX.Data.IBqlField" +
            "\r\n\t\t{\r\n\t\t}\r\n\t\tprotected Byte[] _tstamp;\r\n\t\t[PXDBTimestamp]\r\n\t\tpublic virtual Byte[] " +
            "tstamp\r\n\t\t{\r\n\t\t\tget\r\n\t\t\t{\r\n\t\t\t\treturn this._tstamp;\r\n\t\t\t}\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\tthis._tstamp = value;" +
            "\r\n\t\t\t}\r\n\t\t}\r\n\t\t#endregion";
        cSharp += serviceFields;
        cSharp += "\t\t\r\n}\r\n}";
        txtDacClass.Text = cSharp;
    }
 
    public string SplitCamelCase(string inputString)
    {
        return Regex.Replace(inputString, "(?<=[a-z])([A-Z])"" $1"RegexOptions.Compiled);
    }
 
    public List<ColumnForDacInfo> GetColumnsNames(string tableName)
    {
        List<ColumnForDacInfo> result = new List<ColumnForDacInfo>();
        using (SqlConnection connection = new SqlConnection(txtConnectionString.Text))
        using (SqlCommand command = connection.CreateCommand())
        {
            command.CommandText = $"select * from information_schema.columns where table_name = '{tableName}'";
            connection.Open();
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    var col = new ColumnForDacInfo();
                    col.ColumnName = reader.GetString(
                        reader.GetOrdinal("COLUMN_NAME")
                        );
                    col.ColumnType = reader.GetString(reader.GetOrdinal("DATA_TYPE"));
                    col.ColumnName = reader.GetString(reader.GetOrdinal("COLUMN_NAME"));
                    try
                    {
                        col.MaximumLength = reader.GetInt32(reader.GetOrdinal("CHARACTER_MAXIMUM_LENGTH"));
                    }
                    catch (Exception)
                    {
                    }
 
                    try
                    {
                        col.NumericPresicion = reader.GetInt32(reader.GetOrdinal("NUMERIC_PRECISION"));
                    }
                    catch (Exception)
                    {
                    }
                    try
                    {
                        col.NumericScalse = reader.GetInt32(reader.GetOrdinal("NUMERIC_SCALE"));
                    }
                    catch (Exception)
                    {
                    }
                    try
                    {
                        col.IsNullable = reader.GetString(reader.GetOrdinal("IS_NULLABLE"));
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
 
                    if (!ExcludeFromGeneration.Contains(col.ColumnName))
                    {
                        result.Add(col);
                    }
                }
            }
        }
        return result;
    }
 
    public List<string> ExcludeFromGeneration
    {
        get
        {
            var excludeFromGeneration = new List<string>();
            excludeFromGeneration.Add("CompanyID");
            excludeFromGeneration.Add("tstamp");
            excludeFromGeneration.Add("CreatedByID");
            excludeFromGeneration.Add("CreatedByScreenID");
            excludeFromGeneration.Add("CreatedDateTime");
            excludeFromGeneration.Add("LastModifiedByID");
            excludeFromGeneration.Add("LastModifiedByScreenID");
            excludeFromGeneration.Add("LastModifiedDateTime");
            return excludeFromGeneration;
        }
    }
}

Method FirstCharToUpper as input takes string and returns capitalized first character.

Method SplitCamelCase takes string like "stringLikeThis" and will make it like "string Like This".

Method GetColumNames reads needed information about columns. 

And of course meat of code is btnGenerate_Click method which creates string which you can than copy/paste in your solution.

No Comments

Add a Comment
 

 

How To Create Plugins That Can Be Loaded Unloaded

 

Hello everybody,

today I want to show sample of code that you can use for your plugins.

Sometime it can happen that you have some application with it's dlls and you can decide to make ad hoc dlls.

In order to demonstrate how to do it I prepared following code:

Create first class library as BaseLib:

using System;
 
namespace BaseClass
{
    public class BaseClass : MarshalByRefObject
    {
        public virtual bool IsProcessable(string message)
        {
            return true;
        }
 
        public virtual void Process(string message)
        {
            
        }
    }
}

Then create following implementation:

using System;
namespace Ext1
{
    public class Extension1 : BaseClass.BaseClass
    {
        public override bool IsProcessable(string message)
        {
            return true;
        }
 
        public override void Process(string message)
        {
            message = message + " 1 " + message;
            Console.WriteLine(message);
        }
    }
}

And then code like this will give you possibility to load/unload dlls:

using System;
using System.IO;
using System.Reflection;
 
namespace MarshalByRef
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain ad = AppDomain.CreateDomain("extensions");
            string testDlls = @"d:\sources\MarshalByRef\MarshalByRef\destDlls\";
            string dest = @"d:\sources\MarshalByRef\MarshalByRef\MarshalByRef\bin\Debug\" + "Ext1.dll";
            File.Copy(testDlls + "Ext1.dll", dest, true);
 
            Loader loader = (Loader)ad.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
            loader.LoadAssembly(dest);
            loader.Execute();
            //if you try to delete Ext1.dll you'll got an error
            AppDomain.Unload(ad);
            //if you try to delete Ext1.dll now, you'll be successfull
            Console.ReadKey();
        }
    }
 
    class Loader : MarshalByRefObject
    {
        private Assembly _assembly;
 
        public void LoadAssembly(string path)
        {
            _assembly = Assembly.Load(AssemblyName.GetAssemblyName(path));
        }
 
        public void Execute()
        {
            var instance = _assembly.CreateInstance("Ext1.Extension1"as BaseClass.BaseClass;
            instance.Process("test");
        }
    }
}

No Comments

Add a Comment
 

 

How To Convert Excel File To Csv File

 

Hello everybody,

today I want to document a few lines of code which can help to convert excel file to CSV file with help of OLE:

static void ConvertExcelToCsv(string excelFileName, string csvOutputFileName, int worksheetNumber = 1)
{
    if (!File.Exists(excelFileName)) throw new FileNotFoundException(excelFileName);
    if (File.Exists(csvOutputFileName)) throw new ArgumentException("File already exists: " + csvOutputFileName);
 
    var connectionString =
        $"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={excelFileName};Extended Properties=\"Excel 8.0;IMEX=1;HDR=NO\"";
    var oleDbConnection = new OleDbConnection(connectionString);
 
    // get schema, then data
    var dataTable = new DataTable();
    try
    {
        oleDbConnection.Open();
        var schemaTable = oleDbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
        if (schemaTable != null && schemaTable.Rows.Count < worksheetNumber) throw new ArgumentException("The worksheet number provided cannot be found in the spreadsheet");
        if (schemaTable != null)
        {
            var worksheet = schemaTable.Rows[worksheetNumber - 1]["table_name"].ToString().Replace("'""");
            var sql = $"select * from [{worksheet}]";
            var oleDbDataAdapter = new OleDbDataAdapter(sql, oleDbConnection);
            oleDbDataAdapter.Fill(dataTable);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }
    finally
    {
        // free resources
        oleDbConnection.Close();
    }
 
    // write out CSV data
    using (var streamWriter = new StreamWriter(csvOutputFileName))
    {
        foreach (DataRow row in dataTable.Rows)
        {
            bool firstLine = true;
            foreach (DataColumn col in dataTable.Columns)
            {
                if (!firstLine) { streamWriter.Write(","); } else { firstLine = false; }
                var data = row[col.ColumnName].ToString().Replace("\"""\"\"");
                streamWriter.Write($"\"{data}\"");
            }
            streamWriter.WriteLine();
        }
    }
}

No Comments

Add a Comment
 

 

How To Check If Type In Assembly Implements Particular Interface

 

Hello everybody,

today I want to give sample of reading available types from dll .net assembly, check if at least one of them implements interface, and if implements then to create instance of that type and return it. 

So, imagine you have such interface declaration in your code:

public interface ILogger
    {
        /// <summary>
        /// Convert <see cref="LoggerMessage"/> to string based on the formats specified.
        /// </summary>
        /// <param name="message">The message to be converted.</param>
        /// <returns>Converted <paramref name="message"/>.</returns>
        LoggerMessage Handle(LoggerMessage message);
 
        bool Handlable(LoggerMessage message);     
}

and following implementation of this interface:

public class LoggerDateTimeAdder : ILogger
    {
        public LoggerMessage Handle(LoggerMessage message)
        {
            message.AppendAdditionalInfo("start"DateTime.Now);
            return message;
        }
 
        public bool Handlable(LoggerMessage message)
        {
            return true;
        }
    }

Then you can use following function in order to read your dll and create instance of LoggerDateTimeAdder:

ILogger LoadFromAssembly(string assmFileName)
{
    ILoggerItemFormatter result = null;
    var assembly = Assembly.LoadFile(assmFileName);
 
    foreach (Type exportedType in assembly.ExportedTypes)
    {
        if(typeof(ILogger).IsAssignableFrom(exportedType))
        {
            result = assembly.CreateInstance(exportedType.FullName) as ILogger;
            break;
        }
    }
    return result;
}

No Comments

Add a Comment
 

 

Concurent Collections Of C

 

Hello everybody,

today I want to write few words about Concurent collections in C#. First of all  I want to point there there are only four of them:

  1. ConcurrentDictionary
  2. ConcurrentQueue
  3. ConcurrentStack
  4. ConcurrentBag
  5. BlockingCollection
  6. Partitioner
  7. EnumerablePartitionerOptions
  8. IProducerConsumerCollection
  9. OrderablePartitioner

Not very impressive set of collections if to compare with diversity of other collections in .Net.

Also keep in mind that ConcurrentQueue, ConcurrentStack and ConcurrentBag are not suitable for a lot of purposes. For example those last three do not allow direct access to any element in the collection which makes them unfitting for many goals. In practical life it means that for general purpose thread-safety you can use as usually ConcurrentDictionary. 

But with little bit of imagination, you can use following usages of ConcurrentDictionary.

What you may want What you can use Comments, Warnings
List<T> ConcurrentDictionary<int, T> It will be slower then List, but it will be thread safe
HashSet<T> ConcurrentDictionary<T, T>  
SortedList<TKey, TValue> or SortedDictionary<TKey, TValue> ConcurrentDictionary<TKey, TValue> Sort before using

Now you may wonder what is purpose of ConcurrentQueue, ConcurrentStack, ConcurrentBag, BlockingCollection, IProducerConsumerCollection if they of such of limited usage? The answer is clear: they intended for producer/consumer scenarios. One thread puts something in collection or produced items in collections. Other threads taking items from collections or consuming them.

Few more words about Partitioners collections. They are needed for cases if you need to modify behavior of Parallel.ForEach.

No Comments

Add a Comment