static void InsertElement(this SQLiteConnection conn, object element, bool replace, ISet <object> objectCache)
        {
            var primaryKeyProperty        = element.GetType().GetPrimaryKey();
            var isAutoIncrementPrimaryKey = primaryKeyProperty != null && primaryKeyProperty.GetAttribute <AutoIncrementAttribute>() != null;

            conn.InsertElement(element, replace, primaryKeyProperty, isAutoIncrementPrimaryKey, objectCache);
        }
        static void InsertValue(this SQLiteConnection conn, object value, bool replace, bool recursive, ISet <object> objectCache)
        {
            if (value == null)
            {
                return;
            }

            var enumerable = value as IEnumerable;

            if (recursive)
            {
                if (enumerable != null)
                {
                    conn.InsertAllWithChildrenRecursive(enumerable, replace, recursive, objectCache);
                }
                else
                {
                    conn.InsertWithChildrenRecursive(value, replace, recursive, objectCache);
                }
            }
            else
            {
                if (enumerable != null)
                {
                    conn.InsertElements(enumerable, replace, objectCache);
                }
                else
                {
                    conn.InsertElement(value, replace, objectCache);
                }
            }
        }
        static IEnumerable InsertElements(this SQLiteConnection conn, IEnumerable elements, bool replace, ISet <object> objectCache)
        {
            if (elements == null)
            {
                return(Enumerable.Empty <object>());
            }

            objectCache = objectCache ?? new HashSet <object>();
            var elementsToInsert = elements.Cast <object>().Except(objectCache).ToList();

            if (elementsToInsert.Count == 0)
            {
                return(Enumerable.Empty <object>());
            }

            var primaryKeyProperty        = elementsToInsert[0].GetType().GetPrimaryKey();
            var isAutoIncrementPrimaryKey = primaryKeyProperty != null && primaryKeyProperty.GetAttribute <AutoIncrementAttribute>() != null;

            foreach (var element in elementsToInsert)
            {
                conn.InsertElement(element, replace, primaryKeyProperty, isAutoIncrementPrimaryKey, objectCache);
                objectCache.Add(element);
            }

            return(elementsToInsert);
        }
        static void InsertWithChildrenRecursive(this SQLiteConnection conn, object element, bool replace, bool recursive, ISet <object> objectCache = null)
        {
            objectCache = objectCache ?? new HashSet <object>();
            if (objectCache.Contains(element))
            {
                return;
            }

            conn.InsertElement(element, replace, objectCache);

            objectCache.Add(element);
            conn.InsertChildrenRecursive(element, replace, recursive, objectCache);

            conn.UpdateWithChildren(element);
        }