/// <summary>
        ///
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="result"></param>
        /// <param name="selector"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static EntityResult <TModel> AddExtendedProperty <TModel, TProperty>(this EntityResult <TModel> result, Expression <Func <TModel, TProperty> > selector, string name, string value) where TModel : class
        {
            result.Table[GetPropertyName(selector)].ExtendedProperties.Add(new ExtendedProperty
            {
                Name  = name,
                Value = value
            });

            return(result);
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="result"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static EntityResult <TModel> AddExtendedProperty <TModel>(this EntityResult <TModel> result, string name, string value) where TModel : class
        {
            result.Table.ExtendedProperties.Add(new ExtendedProperty
            {
                Name  = name,
                Value = value
            });

            return(result);
        }
        public static EntityResult <TModel> AddUnique <TModel, TProperty>(this EntityResult <TModel> result, Expression <Func <TModel, TProperty> > selector, string constraintName = null) where TModel : class
        {
            var names = GetPropertyNames(selector).ToList();

            result.Table.Uniques.Add(new Unique
            {
                ConstraintName = constraintName ?? result.Database.NamingConvention.GetUniqueConstraintName(result.Table, names.ToArray()),
                Key            = names
            });

            return(result);
        }
        // todo: Fix the definition for check contraint in Core module

        //public static EntityResult<TModel> AddCheck<TModel, TProperty>(this EntityResult<TModel> result, Expression<Func<TModel, TProperty>> selector, string value, string constraintName = null) where TModel : class
        //{
        //    var names = GetPropertyNames(selector).ToList();

        //    result.Table.Checks.Add(new Check
        //    {
        //        ConstraintName = constraintName ?? result.Database.NamingConvention.GetUniqueConstraintName(result.Table, names.ToArray()),
        //        Key = names
        //    });

        //    return result;
        //}

        public static EntityResult <TModel> AddDefault <TModel, TProperty>(this EntityResult <TModel> result, Expression <Func <TModel, TProperty> > selector, string value, string constraintName = null) where TModel : class
        {
            var names = GetPropertyNames(selector).ToList();

            result.Table.Defaults.Add(new Default
            {
                ConstraintName = constraintName ?? result.Database.NamingConvention.GetDefaultConstraintName(result.Table, names.First()),
                Value          = value
            });

            return(result);
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="result"></param>
        /// <param name="selector"></param>
        /// <param name="constraintName"></param>
        /// <returns></returns>
        public static EntityResult <TModel> SetPrimaryKey <TModel, TProperty>(this EntityResult <TModel> result, Expression <Func <TModel, TProperty> > selector, string constraintName = null) where TModel : class
        {
            var names = GetPropertyNames(selector).ToList();

            result.Table.PrimaryKey = new PrimaryKey
            {
                ConstraintName = result.Database.NamingConvention.GetPrimaryKeyConstraintName(result.Table, names.ToArray()),
                Key            = names
            };

            return(result);
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="result"></param>
        /// <param name="selector"></param>
        /// <param name="table"></param>
        /// <param name="constraintName"></param>
        /// <returns></returns>
        public static EntityResult <TModel> AddForeignKey <TModel, TProperty>(this EntityResult <TModel> result, Expression <Func <TModel, TProperty> > selector, Table table, string constraintName = null) where TModel : class
        {
            var names = GetPropertyNames(selector).ToList();

            result.Table.ForeignKeys.Add(new ForeignKey
            {
                ConstraintName = string.IsNullOrEmpty(constraintName) ? result.Database.NamingConvention.GetForeignKeyConstraintName(result.Table, names.ToArray(), table) : constraintName,
                Key            = GetPropertyNames(selector).ToList(),
                References     = table.FullName
            });

            return(result);
        }
#pragma warning disable CS1591
        public static EntityResult <TModel> DefineEntity <TModel>(this SqlServerDatabase database, TModel model) where TModel : class
        {
            var result = new EntityResult <TModel>
            {
                Table = new Table
                {
                    Schema = database.DefaultSchema,
                    Name   = model.GetType().Name
                },
                Database = database,
                Model    = model
            };

            result.Table.ImportBag.ExtendedProperties = new Collection <ExtendedProperty>();

            foreach (var property in model.GetType().GetProperties())
            {
                var propType = property.PropertyType;

                var defType = database.DefaultTypeMaps.FirstOrDefault(item => item.Type == propType);

                var type = string.Empty;

                if (defType == null)
                {
                    var types = database.GetDatabaseTypeMaps(propType).ToList();

                    type = types.Count == 0 ? "" : types.First().DatabaseType;
                }
                else
                {
                    type = defType.DatabaseType;
                }

                result.Table.Columns.Add(new Column
                {
                    Name = property.Name,
                    Type = type
                });

                result.Table.Columns.Last().ImportBag.ExtendedProperties = new Collection <ExtendedProperty>();
            }

            database.Tables.Add(result.Table);

            return(result);
        }
        public static EntityResult <TModel> SetColumnFor <TModel>(this EntityResult <TModel> result, Expression <Func <TModel, TimeSpan?> > selector, bool nullable = false) where TModel : class
        {
            var column = new Column
            {
                Name = GetPropertyName(selector)
            };

            if (result.Table.Columns.Contains(column))
            {
                result.Table[column.Name].Nullable = nullable;
            }
            else
            {
                result.Table.Columns.Add(column);
            }

            return(result);
        }
        public static EntityResult <TModel> SetColumnFor <TModel>(this EntityResult <TModel> result, Expression <Func <TModel, short?> > selector, string type = "", bool nullable = false) where TModel : class
        {
            var column = new Column
            {
                Name = GetPropertyName(selector)
            };

            if (result.Table.Columns.Contains(column))
            {
                if (!string.IsNullOrEmpty(type))
                {
                    result.Table[column.Name].Type = type;
                }

                result.Table[column.Name].Nullable = nullable;
            }
            else
            {
                result.Table.Columns.Add(column);
            }

            return(result);
        }
        public static EntityResult <TModel> AddExtendedProperty <TModel>(this EntityResult <TModel> result, string name, string value) where TModel : class
        {
            result.Table.ImportBag.ExtendedProperties.Add(new ExtendedProperty(name, value));

            return(result);
        }
        public static EntityResult <TModel> SetIdentity <TModel>(this EntityResult <TModel> result, Expression <Func <TModel, short?> > selector, int seed = 1, int increment = 1) where TModel : class
        {
            result.Table.Identity = new Identity(GetPropertyName(selector), seed, increment);

            return(result);
        }