/// <summary>
        /// Construct filter expression for entity.
        /// </summary>
        /// <param name="entity">Entity to construct filter expression for.</param>
        /// <param name="typeOfFilter">Type of filter expression.</param>
        /// <returns>Filter expression according to entity.</returns>
        public Expression <Func <TEntity, bool> > ConstructFilterExpression(
            TEntity entity,
            FilterType typeOfFilter)
        {
            Expression <Func <TEntity, bool> > filterExpression = null;
            IEnumerable <string> primaryKeyNames = GetPrimaryKeys();

            if (primaryKeyNames.Count() == 0)
            {
                throw new ArgumentException(string.Format(
                                                "'{0}' has no configured primary key.",
                                                typeof(TEntity).Name));
            }

            List <Expression>        equalityExpressions = new List <Expression>();
            IEnumerable <Expression> singleExpressionList;

            ParameterExpression parameterExp = Expression.Parameter(typeof(TEntity), "m");
            Expression          pkFilter     = null;
            Expression          ukFilter     = null;

            bool primaryKeysHaveDefaultValues = entity.HasDefaultValues(primaryKeyNames);

            if (!primaryKeysHaveDefaultValues &&
                typeOfFilter != FilterType.OnlyUnique)
            {
                // If primary keys do not have their default values
                // add this check to equlity expression list
                singleExpressionList = parameterExp
                                       .ConstructEqualityExpressions(
                    entity,
                    primaryKeyNames);

                pkFilter = singleExpressionList.ConstructAndChain();
            }

            if (typeOfFilter != FilterType.OnlyId &&
                (primaryKeysHaveDefaultValues ||
                 typeOfFilter != FilterType.IdOptionalUnique))
            {
                IEnumerable <PropertiesWithSource> uniqueProperties =
                    MappingStorage.Instance.UniqueProperties.Where(
                        m => m.SourceType.Equals(entity.GetType()));

                if (uniqueProperties.Count() > 0)
                {
                    foreach (PropertiesWithSource unique in uniqueProperties)
                    {
                        /*
                         ***********************************************************
                         * If any of current set of properties
                         * marked as unique is foreign key,
                         * has default value, and appropriate navigation property is not
                         * null and also origin of this foreign
                         * key has any store generated primary key then this
                         * uniqueness must be ignored.
                         * For example if PersonId (int) and DocumentType (short) has been
                         * set as composite unique in PersonDocument and
                         * if PersonId is foreign key to Person, which in its term has
                         * Primary key which is store generated and if there is no navigation
                         * property to Person from PersonDocument or PersonDocument.Person is not null
                         * then PersonId = 0 and DocumentType = 5 should not
                         * be treated as unique, because the real value of PersonId
                         * will be computed when data will be inserted.
                         ***********************************************************
                         */

                        IGraphEntityTypeManager uniqueSourceTypeManager = ContextFactory
                                                                          .GetEntityTypeManager(unique.SourceType.Name);

                        bool uniquenessMustBeIgnored = false;

                        var uniquePropertyNames = unique.Properties.Select(m => m.Name).ToList();
                        var uniqueForeignKeys   = uniqueSourceTypeManager
                                                  .GetForeignKeyDetails()
                                                  .Select(m => new
                        {
                            TargetClass = m.FromDetails.ContainerClass,
                            Keys        = m.ToDetails.Keys.Intersect(uniquePropertyNames)
                        })
                                                  .Where(m => m.Keys != null &&
                                                         m.Keys.Any());

                        NavigationDetail navigationDetailsOfCurrent = GetNavigationDetail();

                        // If unuque property is foreign key
                        if (uniqueForeignKeys != null &&
                            uniqueForeignKeys.Any())
                        {
                            foreach (var uniqueFk in uniqueForeignKeys)
                            {
                                // If foreign key has default value
                                if (uniqueFk.Keys.Any(u => entity.HasDefaultValue(u)))
                                {
                                    // Get navigation relation according to foreign key
                                    NavigationRelation navigationRelation = navigationDetailsOfCurrent
                                                                            .Relations
                                                                            .FirstOrDefault(r => r.Direction == NavigationDirection.From &&
                                                                                            r.PropertyTypeName.Equals(uniqueFk.TargetClass) &&
                                                                                            r.ToKeyNames.Intersect(uniqueFk.Keys).Any());

                                    // If corresponding navigation property is not null
                                    // or there is no such navigation property
                                    if (navigationRelation == null ||
                                        entity.GetPropertyValue(navigationRelation.PropertyName) != null)
                                    {
                                        bool foreignKeyHasStoreGeneratedPrimaryKey =
                                            uniqueFk.Keys.Any(k =>
                                        {
                                            // Get origin of foreign key and check
                                            // if it has store generated key.
                                            string foreignKeyOrigin = uniqueSourceTypeManager
                                                                      .GetOriginOfForeignKey(k);
                                            IGraphEntityTypeManager foreignKeyOriginTypeManger = ContextFactory
                                                                                                 .GetEntityTypeManager(foreignKeyOrigin);
                                            return(foreignKeyOriginTypeManger.HasStoreGeneratedKey());
                                        });

                                        // If origin of foreign key has store generated Primary key
                                        if (foreignKeyHasStoreGeneratedPrimaryKey)
                                        {
                                            uniquenessMustBeIgnored = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        // If uniqueness must be ignored then skip this iteration
                        if (uniquenessMustBeIgnored)
                        {
                            continue;
                        }

                        singleExpressionList = parameterExp
                                               .ConstructEqualityExpressions(
                            entity,
                            unique.Properties
                            .Select(m => m.Name).ToList());
                        equalityExpressions.Add(singleExpressionList.ConstructAndChain());
                    }

                    if (equalityExpressions.Count > 0)
                    {
                        ukFilter = equalityExpressions.ConstructOrChain();
                    }
                }
            }

            equalityExpressions.Clear();
            if (pkFilter != null)
            {
                equalityExpressions.Add(pkFilter);
            }

            if (ukFilter != null)
            {
                equalityExpressions.Add(ukFilter);
            }

            if (equalityExpressions.Count > 0)
            {
                Expression filterBaseExpression = typeOfFilter == FilterType.IdAndUnique
                    ? equalityExpressions.ConstructAndChain()
                    : equalityExpressions.ConstructOrChain();

                filterExpression = Expression.Lambda <Func <TEntity, bool> >(
                    filterBaseExpression, parameterExp);
            }

            return(filterExpression);
        }