public virtual SqlQuery CreateQuery(object entity, IEntityMetaData metaData, out PropertyMetaData identity)
        {
            EntitySqlQueryBuilderUpdate builderUpdate = new EntitySqlQueryBuilderUpdate();
            builderUpdate.ParameterIndex = this.ParameterIndex;
            builderUpdate.UpdatedFields = this.UpdatedFields;

            SqlQuery query = builderUpdate.CreateQuery(entity, metaData);
            StringBuilder text = query.Text;

            text.AppendLine();
            text.Append("IF @@ROWCOUNT = 0");
            text.AppendLine();
            text.Append("BEGIN");
            text.AppendLine();

            EntitySqlQueryBuilderInsert builderInsert = new EntitySqlQueryBuilderInsert();
            builderInsert.ParameterIndex = this.ParameterIndex;
            builderInsert.InsertFields = this.InsertFields;
            query.Combine(builderInsert.CreateQuery(entity, metaData, out identity));

            text.AppendLine();
            text.Append("END");

            return query;
        }
        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());
            }
        }