protected override int ExecuteInternal(IEnumerable<IEntityChange> changes, BatchCommandMode mode, IEntityMetaData metaData)
        {
            PropertyMetaData identity = null;
            Dictionary<string, object> outs = new Dictionary<string, object>();

            IEnumerable<IEntityChange> modified = changes.Where(e => e.State == EntityState.Modified);
            IEnumerable<IEntityChange> deleted = changes.Where(e => e.State == EntityState.Deleted);
            IEnumerable<IEntityChange> added = changes.Where(e => e.State == EntityState.Added);

            switch (mode)
            {
                case BatchCommandMode.Batch:

                    SqlQuery batchQuery = new SqlQuery();

                    batchQuery.Text.Append(GlobalInternal.SqlServerBeginStatement);
                    batchQuery.Text.AppendLine();

                    int index = 0;

                    if (!modified.IsEmptyList())
                    {
                        EntitySqlQueryBuilderUpdate updateBuilder = new EntitySqlQueryBuilderUpdate();
                        foreach (IEntityChange change in modified)
                        {
                            updateBuilder.ParameterIndex = index++;
                            updateBuilder.UpdatedFields = change.UpdatedFields;
                            batchQuery.Combine(updateBuilder.CreateQuery(change.Entity, metaData));
                            batchQuery.Text.AppendLine();
                        }
                        batchQuery.Text.AppendLine();
                    }

                    if (!deleted.IsEmptyList())
                    {
                        foreach (IEntityChange change in deleted)
                        {
                            SqlQuery deleteQuery = new SqlQuery();
                            deleteQuery.Text.Append("DELETE FROM ");
                            deleteQuery.Text.Append(metaData.TableName);

                            SqlQueryHelper.IndexParameterNames(metaData, index++);

                            deleteQuery.Combine(SqlQueryHelper.CreateWhereSqlByKeys(metaData, '@', change.Entity));

                            batchQuery.Combine(deleteQuery);
                            batchQuery.Text.AppendLine();
                        }
                        batchQuery.Text.AppendLine();
                    }

                    if (!added.IsEmptyList())
                    {
                        EntitySqlQueryBuilderInsert insertBuilder = new EntitySqlQueryBuilderInsert();
                        foreach (IEntityChange change in added)
                        {
                            insertBuilder.ParameterIndex = index++;
                            batchQuery.Combine(insertBuilder.CreateQuery(change.Entity, metaData, out identity));
                            if (null != identity)
                                outs.Add(identity.ParameterName, change.Entity);

                            batchQuery.Text.AppendLine();
                        }
                    }

                    batchQuery.Text.Append(GlobalInternal.SqlServerEndStatement);

                    int ret = base.DataAccess.ExecuteNonQuery(batchQuery);

                    if (null != identity)//outParameterNames.Count must be equal to entityList.Count.
                    {
                        foreach (KeyValuePair<string, object> kvp in outs)
                        {
                            string outParameterName = kvp.Key;
                            object identityValue = batchQuery.Parameters.Find(outParameterName).Value;
                            identity.Property.SetValue(kvp.Value, identityValue, null);
                        }
                    }

                    return ret;

                case BatchCommandMode.Single:
                    int sum = 0;

                    if (!modified.IsEmptyList())
                    {
                        EntityCommandUpdate updateCommand = new EntityCommandUpdate(base.DataAccess);
                        foreach (IEntityChange change in modified)
                        {
                            updateCommand.UpdatedFields = change.UpdatedFields;
                            sum += updateCommand.UpdateInternal(change.Entity, metaData);
                        }
                    }

                    if (!deleted.IsEmptyList())
                    {
                        EntityCommandDelete deleteCommand = new EntityCommandDelete(base.DataAccess);
                        foreach (IEntityChange change in deleted)
                        {
                            sum += deleteCommand.DeleteInternal(change.Entity, metaData);
                        }
                    }

                    if (!added.IsEmptyList())
                    {
                        EntityCommandInsert insertCommand = new EntityCommandInsert(base.DataAccess);
                        foreach (IEntityChange change in added)
                        {
                            sum += insertCommand.InsertInternal(change.Entity, metaData);
                        }
                    }

                    return sum;

                default:
                    throw new NotSupportedException(mode.ToString());
            }
        }
        protected override int ExecuteInternal(IEnumerable<IEntityChange> changes, BatchCommandMode mode, IEntityMetaData metaData)
        {
            IEnumerable<IEntityChange> modified = changes.Where(e => e.State == EntityState.Modified);
            IEnumerable<IEntityChange> deleted = changes.Where(e => e.State == EntityState.Deleted);
            IEnumerable<IEntityChange> added = changes.Where(e => e.State == EntityState.Added);

            switch (mode)
            {
                case BatchCommandMode.Batch:

                    SqlQuery batchQuery = new SqlQuery();

                    batchQuery.Text.Append(GlobalInternal.BeginStatement);
                    batchQuery.Text.AppendLine();

                    int index = 0;

                    if (!modified.IsEmptyList())
                    {
                        EntitySqlQueryBuilderUpdate updateBuilder = new EntitySqlQueryBuilderUpdate() { UseSemicolon = true };
                        foreach (IEntityChange change in modified)
                        {
                            updateBuilder.ParameterIndex = index++;
                            updateBuilder.UpdatedFields = change.UpdatedFields;
                            batchQuery.Combine(updateBuilder.CreateQuery(change.Entity, metaData));
                            batchQuery.Text.AppendLine();
                        }
                        batchQuery.Text.AppendLine();
                    }

                    if (!deleted.IsEmptyList())
                    {
                        foreach (IEntityChange change in deleted)
                        {
                            SqlQuery deleteQuery = new SqlQuery();
                            deleteQuery.Text.Append("DELETE FROM ");
                            deleteQuery.Text.Append(metaData.TableName);

                            SqlQueryHelper.IndexParameterNames(metaData, index++);

                            deleteQuery.Combine(SqlQueryHelper.CreateWhereSqlByKeys(metaData, '@', change.Entity));

                            batchQuery.Combine(deleteQuery);
                            batchQuery.Text.AppendLine(";");
                        }
                        batchQuery.Text.AppendLine();
                    }

                    if (!added.IsEmptyList())
                    {
                        PropertyMetaData sequenceIdentity = null;
                        EntitySqlQueryBuilderInsert insertBuilder = new EntitySqlQueryBuilderInsert() { UseSemicolon = true };
                        foreach (IEntityChange change in added)
                        {
                            insertBuilder.ParameterIndex = index++;
                            batchQuery.Combine(insertBuilder.CreateQuery(change.Entity, metaData, out sequenceIdentity));

                            batchQuery.Text.AppendLine();
                        }
                    }

                    batchQuery.Text.Append(GlobalInternal.EndStatement);

                    return base.DataAccess.ExecuteNonQuery(batchQuery);

                case BatchCommandMode.Single:
                    int sum = 0;

                    if (!modified.IsEmptyList())
                    {
                        EntityCommandUpdate updateCommand = new EntityCommandUpdate(base.DataAccess);
                        foreach (IEntityChange change in modified)
                        {
                            updateCommand.UpdatedFields = change.UpdatedFields;
                            sum += updateCommand.UpdateInternal(change.Entity, metaData);
                        }
                    }

                    if (!deleted.IsEmptyList())
                    {
                        EntityCommandDelete deleteCommand = new EntityCommandDelete(base.DataAccess);
                        foreach (IEntityChange change in deleted)
                        {
                            sum += deleteCommand.DeleteInternal(change.Entity, metaData);
                        }
                    }

                    if (!added.IsEmptyList())
                    {
                        EntityCommandInsert insertCommand = new EntityCommandInsert(base.DataAccess);
                        foreach (IEntityChange change in added)
                        {
                            sum += insertCommand.InsertInternal(change.Entity, metaData);
                        }
                    }

                    return sum;

                default:
                    throw new NotSupportedException(mode.ToString());
            }
        }