/// <summary>
        /// DeSerilize Xml to object, this is supposed to handle all unknow object types but there has not been to many tests.
        /// </summary>
        /// <param name="xml"></param>
        /// <param name="transaction"></param>
        /// <returns></returns>
        public static object FromXml(this string xml, IRepository transaction = null)
        {
            if (string.IsNullOrEmpty(xml))
            {
                return(null);
            }
            var doc = new System.Xml.XmlDocument();

            doc.LoadXml(xml);
            var o = FromXml(doc.DocumentElement);

            void LoadXmlIgnoreProperties(object item)
            {
                if (item is IList)
                {
                    foreach (var t in (IList)item)
                    {
                        LoadXmlIgnoreProperties(t);
                    }
                    return;
                }

                var type = item?.GetType().GetActualType();

                if (type == null)
                {
                    return;
                }
                if (!(item?.GetPrimaryKeyValue().ObjectIsNew() ?? true))
                {
                    var primaryId = item.GetPrimaryKeyValue();
                    foreach (var prop in DeepCloner.GetFastDeepClonerProperties(item.GetType()).Where(x => (x.ContainAttribute <XmlIgnore>() || !x.IsInternalType) && !x.ContainAttribute <ExcludeFromAbstract>() && x.CanReadWrite))
                    {
                        var value = prop.GetValue(item);
                        if (prop.PropertyType == typeof(string) && string.IsNullOrEmpty(value?.ToString()))
                        {
                            value = string.Empty;
                        }
                        if (prop.IsInternalType && value == LightDataTableShared.ValueByType(prop.PropertyType)) // Value is default
                        {
                            var cmd  = transaction.GetSqlCommand($"SELECT [{prop.GetPropertyName()}] FROM {type.TableName().GetName(transaction.DataBaseTypes)} WHERE [{item.GetPrimaryKey().GetPropertyName()}] = {Querys.GetValueByType(item.GetPrimaryKeyValue(), transaction.DataBaseTypes)}");
                            var data = transaction.ExecuteScalar(cmd);
                            if (data == null)
                            {
                                continue;
                            }
                            if (prop.ContainAttribute <DataEncode>())
                            {
                                data = new DataCipher(prop.GetCustomAttribute <DataEncode>().Key, prop.GetCustomAttribute <DataEncode>().KeySize).Decrypt(data.ToString());
                            }
                            else if (prop.ContainAttribute <ToBase64String>() && data.ToString().IsBase64String())
                            {
                                data = MethodHelper.DecodeStringFromBase64(data.ToString());
                            }

                            prop.SetValue(item, data.ConvertValue(prop.PropertyType));
                        }
                        else if (value != null)
                        {
                            LoadXmlIgnoreProperties(value);
                        }
                    }
                }
            }

            if (transaction != null)
            {
                LoadXmlIgnoreProperties(o);
            }
            return(o);
        }