當前位置: 首頁>>代碼示例>>C#>>正文


C# SqlCommand.SqlCommandInfo類代碼示例

本文整理匯總了C#中NHibernate.SqlCommand.SqlCommandInfo的典型用法代碼示例。如果您正苦於以下問題:C# SqlCommandInfo類的具體用法?C# SqlCommandInfo怎麽用?C# SqlCommandInfo使用的例子?那麽, 這裏精選的類代碼示例或許可以為您提供幫助。


SqlCommandInfo類屬於NHibernate.SqlCommand命名空間,在下文中一共展示了SqlCommandInfo類的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的C#代碼示例。

示例1: PerformInsert

		public object PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
		{
			try
			{
				// prepare and execute the insert
				IDbCommand insert = session.Batcher.PrepareCommand(insertSQL.CommandType, insertSQL.Text, insertSQL.ParameterTypes);
				try
				{
					binder.BindValues(insert);
					session.Batcher.ExecuteNonQuery(insert);
				}
				finally
				{
					session.Batcher.CloseCommand(insert, null);
				}
			}
			catch (DbException sqle)
			{
				throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle,
				                                 "could not insert: " + persister.GetInfoString(), insertSQL.Text);
			}

			SqlString selectSQL = SelectSQL;
			using (new SessionIdLoggingContext(session.SessionId)) 
			try
			{
				//fetch the generated id in a separate query
				IDbCommand idSelect = session.Batcher.PrepareCommand(CommandType.Text, selectSQL, ParametersTypes);
				try
				{
					BindParameters(session, idSelect, binder.Entity);
					IDataReader rs = session.Batcher.ExecuteReader(idSelect);
					try
					{
						return GetResult(session, rs, binder.Entity);
					}
					finally
					{
						session.Batcher.CloseReader(rs);
					}
				}
				finally
				{
					session.Batcher.CloseCommand(idSelect, null);
				}
			}
			catch (DbException sqle)
			{
				throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle,
				                                 "could not retrieve generated id after insert: " + persister.GetInfoString(),
				                                 insertSQL.Text);
			}
		}
開發者ID:KaraokeStu,項目名稱:nhibernate-core,代碼行數:53,代碼來源:AbstractSelectingDelegate.cs

示例2: Prepare

		protected internal override IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session)
		{
			IDbCommand command = session.Batcher.PrepareCommand(CommandType.Text, insertSQL.Text, insertSQL.ParameterTypes);
			//Add the output parameter
			IDbDataParameter idParameter = factory.ConnectionProvider.Driver.GenerateParameter(command, ReturnParameterName,
			                                                                                         paramType);
			driveGeneratedParamName = idParameter.ParameterName;
			idParameter.Direction = ParameterDirection.ReturnValue;

			command.Parameters.Add(idParameter);
			return command;
		}
開發者ID:hazzik,項目名稱:nh-contrib-everything,代碼行數:12,代碼來源:OutputParamReturningDelegate.cs

示例3: Prepare

		protected internal override IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session)
		{
			IDbCommand command = session.Batcher.PrepareCommand(CommandType.Text, insertSQL.Text, insertSQL.ParameterTypes);
			//Add the output parameter
			IDbDataParameter idParameter = factory.ConnectionProvider.Driver.GenerateParameter(command, ReturnParameterName,
			                                                                                         paramType);
			driveGeneratedParamName = idParameter.ParameterName;

            if (factory.Dialect.InsertGeneratedIdentifierRetrievalMethod == InsertGeneratedIdentifierRetrievalMethod.OutputParameter)
                idParameter.Direction = ParameterDirection.Output;
            else if (factory.Dialect.InsertGeneratedIdentifierRetrievalMethod == InsertGeneratedIdentifierRetrievalMethod.ReturnValueParameter)
                idParameter.Direction = ParameterDirection.ReturnValue;
            else
                throw new System.NotImplementedException("Unsupported InsertGeneratedIdentifierRetrievalMethod: " + factory.Dialect.InsertGeneratedIdentifierRetrievalMethod);

			command.Parameters.Add(idParameter);
			return command;
		}
開發者ID:marchlud,項目名稱:nhibernate-core,代碼行數:18,代碼來源:OutputParamReturningDelegate.cs

示例4: PerformInsert

 public object PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
 {
     try
     {
         // prepare and execute the insert
         IDbCommand insert = Prepare(insertSQL, session);
         try
         {
             binder.BindValues(insert);
             return ExecuteAndExtract(insert, session);
         }
         finally
         {
             ReleaseStatement(insert, session);
         }
     }
     catch (DbException sqle)
     {
         throw ADOExceptionHelper.Convert(session.Factory.SQLExceptionConverter, sqle,
                                          "could not insert: " + MessageHelper.InfoString(persister), insertSQL.Text);
     }
 }
開發者ID:zibler,項目名稱:zibler,代碼行數:22,代碼來源:AbstractReturningDelegate.cs

示例5: Prepare

 protected internal abstract IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session);
開發者ID:zibler,項目名稱:zibler,代碼行數:1,代碼來源:AbstractReturningDelegate.cs

示例6: GenerateSQLDeleteStrings

		protected SqlCommandInfo[] GenerateSQLDeleteStrings(object[] loadedState)
		{
			int span = TableSpan;
			SqlCommandInfo[] deleteStrings = new SqlCommandInfo[span];

			for (int j = span - 1; j >= 0; j--)
			{
				SqlDeleteBuilder delete = new SqlDeleteBuilder(Factory.Dialect, Factory)
					.SetTableName(GetTableName(j))
					.SetIdentityColumn(GetKeyColumns(j), IdentifierType);

				if (Factory.Settings.IsCommentsEnabled)
				{
					delete.SetComment("delete " + EntityName + " [" + j + "]");
				}

				bool[] versionability = PropertyVersionability;
				IType[] types = PropertyTypes;
				for (int i = 0; i < entityMetamodel.PropertySpan; i++)
				{
					bool include = versionability[i] &&
												 IsPropertyOfTable(i, j);

					if (include)
					{
						// this property belongs to the table and it is not specifically
						// excluded from optimistic locking by optimistic-lock="false"
						string[] _propertyColumnNames = GetPropertyColumnNames(i);
						bool[] propertyNullness = types[i].ToColumnNullness(loadedState[i], Factory);
						SqlType[] sqlt = types[i].SqlTypes(Factory);
						for (int k = 0; k < propertyNullness.Length; k++)
						{
							if (propertyNullness[k])
							{
								delete.AddWhereFragment(_propertyColumnNames[k], sqlt[k], " = ");
							}
							else
							{
								delete.AddWhereFragment(_propertyColumnNames[k] + " is null");
							}
						}
					}
				}
				deleteStrings[j] = delete.ToSqlCommandInfo();
			}

			return deleteStrings;
		}
開發者ID:rbirkby,項目名稱:nhibernate-core,代碼行數:48,代碼來源:AbstractEntityPersister.cs

示例7: Delete

		/// <summary>
		/// Perform an SQL DELETE
		/// </summary>
		public void Delete(object id, object version, int j, object obj, SqlCommandInfo sql, ISessionImplementor session,
											 object[] loadedState)
		{
			if (IsInverseTable(j))
			{
				return;
			}

			// NH : Only use version if lock mode is Version
			bool useVersion = j == 0 && IsVersioned && Versioning.OptimisticLock.Version == entityMetamodel.OptimisticLockMode;

			//bool callable = IsDeleteCallable(j);
			IExpectation expectation = Expectations.AppropriateExpectation(deleteResultCheckStyles[j]);
			bool useBatch = j == 0 && expectation.CanBeBatched && IsBatchable;

			if (log.IsDebugEnabled)
			{
				log.Debug("Deleting entity: " + MessageHelper.InfoString(this, id, Factory));
				if (useVersion)
				{
					log.Debug("Version: " + version);
				}
			}

			if (IsTableCascadeDeleteEnabled(j))
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("delete handled by foreign key constraint: " + GetTableName(j));
				}
				return; //EARLY EXIT!
			}

			try
			{
				int index = 0;
				IDbCommand statement;
				if (useBatch)
				{
					statement = session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes);
				}
				else
				{
					statement = session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes);
				}

				try
				{
					//index += expectation.Prepare(statement, factory.ConnectionProvider.Driver);

					// Do the key. The key is immutable so we can use the _current_ object state - not necessarily
					// the state at the time the delete was issued
					IdentifierType.NullSafeSet(statement, id, index, session);
					index += IdentifierColumnSpan;

					// We should use the _current_ object state (ie. after any updates that occurred during flush)
					if (useVersion)
					{
						VersionType.NullSafeSet(statement, version, index, session);
					}
					else if (entityMetamodel.OptimisticLockMode > Versioning.OptimisticLock.Version && loadedState != null)
					{
						bool[] versionability = PropertyVersionability;
						IType[] types = PropertyTypes;
						for (int i = 0; i < entityMetamodel.PropertySpan; i++)
						{
							if (IsPropertyOfTable(i, j) && versionability[i])
							{
								// this property belongs to the table and it is not specifically
								// excluded from optimistic locking by optimistic-lock="false"
								bool[] settable = types[i].ToColumnNullness(loadedState[i], Factory);

								types[i].NullSafeSet(statement, loadedState[i], index, settable, session);
								index += ArrayHelper.CountTrue(settable);
							}
						}
					}

					if (useBatch)
					{
						session.Batcher.AddToBatch(expectation);
					}
					else
					{
						Check(session.Batcher.ExecuteNonQuery(statement), id, j, expectation, statement);
					}
				}
				catch (Exception e)
				{
					if (useBatch)
					{
						session.Batcher.AbortBatch(e);
					}
					throw;
				}
				finally
				{
//.........這裏部分代碼省略.........
開發者ID:rbirkby,項目名稱:nhibernate-core,代碼行數:101,代碼來源:AbstractEntityPersister.cs

示例8: UpdateOrInsert

		/// <summary> Perform an SQL UPDATE or SQL INSERT</summary>
		protected internal virtual void UpdateOrInsert(object id, object[] fields, object[] oldFields, object rowId,
			bool[] includeProperty, int j, object oldVersion, object obj, SqlCommandInfo sql, ISessionImplementor session)
		{
			if (!IsInverseTable(j))
			{
				bool isRowToUpdate;
				if (IsNullableTable(j) && oldFields != null && IsAllNull(oldFields, j))
				{
					//don't bother trying to update, we know there is no row there yet
					isRowToUpdate = false;
				}
				else if (IsNullableTable(j) && IsAllNull(fields, j))
				{
					//if all fields are null, we might need to delete existing row
					isRowToUpdate = true;
					Delete(id, oldVersion, j, obj, SqlDeleteStrings[j], session, null);
				}
				else
				{
					//there is probably a row there, so try to update
					//if no rows were updated, we will find out
					isRowToUpdate = Update(id, fields, oldFields, rowId, includeProperty, j, oldVersion, obj, sql, session);
				}

				if (!isRowToUpdate && !IsAllNull(fields, j))
				{
					// assume that the row was not there since it previously had only null
					// values, so do an INSERT instead
					//TODO: does not respect dynamic-insert
					Insert(id, fields, PropertyInsertability, j, SqlInsertStrings[j], obj, session);
				}
			}
		}
開發者ID:rbirkby,項目名稱:nhibernate-core,代碼行數:34,代碼來源:AbstractEntityPersister.cs

示例9: Insert

		/// <summary>
		/// Perform an SQL INSERT, and then retrieve a generated identifier.
		/// </summary>
		/// <remarks>
		/// This form is used for PostInsertIdentifierGenerator-style ids (IDENTITY, select, etc).
		/// </remarks>
		protected object Insert(object[] fields, bool[] notNull, SqlCommandInfo sql, object obj, ISessionImplementor session)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("Inserting entity: " + EntityName + " (native id)");
				if (IsVersioned)
				{
					log.Debug("Version: " + Versioning.GetVersion(fields, this));
				}
			}
			IBinder binder = new GeneratedIdentifierBinder(fields, notNull, session, obj, this);
			return identityDelegate.PerformInsert(sql, session, binder);
		}
開發者ID:rbirkby,項目名稱:nhibernate-core,代碼行數:19,代碼來源:AbstractEntityPersister.cs

示例10: Insert

		/// <summary>
		/// Persist an object, using a natively generated identifier
		/// </summary>
		protected object Insert(object[] fields, bool[] notNull, SqlCommandInfo sql, object obj, ISessionImplementor session)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("Inserting entity: " + ClassName + " (native id)");
				if (IsVersioned)
				{
					log.Debug("Version: " + Versioning.GetVersion(fields, this));
				}
			}

			try
			{
				SqlString insertSelectSQL = null;

				if (sql.CommandType == CommandType.Text)
				{
					insertSelectSQL = Dialect.AddIdentitySelectToInsert(sql.Text, GetKeyColumns(0)[0], GetTableName(0));
				}

				if (insertSelectSQL != null)
				{
					// Use one statement to insert the row and get the generated id
					IDbCommand insertSelect = session.Batcher.PrepareCommand(CommandType.Text, insertSelectSQL, sql.ParameterTypes);
					IDataReader rs = null;
					try
					{
						// Well, it's always the first table to dehydrate, so pass 0 as the position
						Dehydrate(null, fields, notNull, propertyColumnInsertable, 0, insertSelect, session, 0);
						rs = session.Batcher.ExecuteReader(insertSelect);
						return GetGeneratedIdentity(obj, session, rs);
					}
					finally
					{
						session.Batcher.CloseCommand(insertSelect, rs);
					}
				}
				else
				{
					// Do the insert
					IDbCommand statement = session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes);
					try
					{
						// Well, it's always the first table to dehydrate, so pass 0 as the position
						Dehydrate(null, fields, notNull, propertyColumnInsertable, 0, statement, session, 0);
						session.Batcher.ExecuteNonQuery(statement);

						// Fetch the generated id in a separate query. This is done inside the first try/finally block
						// to keep the insert command open, so that the batcher does not close the connection.
						//
						// It's possible that some ADO.NET provider will not allow two open IDbCommands for the same connection,
						// in that case we'll have to rewrite the code to use some sort of lock on IBatcher.
						SqlString idselectSql = new SqlString(SqlIdentitySelect(IdentifierColumnNames[0], GetTableName(0)));
						IDbCommand idselect = session.Batcher.PrepareCommand(CommandType.Text, idselectSql, SqlTypeFactory.NoTypes);
						IDataReader rs = null;

						try
						{
							rs = session.Batcher.ExecuteReader(idselect);
							return GetGeneratedIdentity(obj, session, rs);
						}
						finally
						{
							session.Batcher.CloseCommand(idselect, rs);
						}
					}
					finally
					{
						session.Batcher.CloseCommand(statement, null);
					}
				}
			}
			catch (HibernateException)
			{
				// Do not call Convert on HibernateExceptions
				throw;
			}
			catch (Exception sqle)
			{
				throw Convert(sqle, "could not insert: " + MessageHelper.InfoString(this), sql.Text);
			}
		}
開發者ID:Novthirteen,項目名稱:sconit_timesseiko,代碼行數:85,代碼來源:AbstractEntityPersister.cs

示例11: Update

		protected void Update(
			object id,
			object[] fields,
			object[] oldFields,
			bool[] includeProperty,
			int j,
			object oldVersion,
			object obj,
			SqlCommandInfo sql,
			ISessionImplementor session)
		{
			bool useVersion = j == 0 && IsVersioned;
			IExpectation expectation = Expectations.AppropriateExpectation(updateResultCheckStyles[j]);
			bool useBatch = j == 0 && expectation.CanBeBatched && IsBatchable;
				//note: updates to joined tables can't be batched...

			if (log.IsDebugEnabled)
			{
				log.Debug("Updating entity: " + MessageHelper.InfoString(this, id));
				if (useVersion)
				{
					log.Debug("Existing version: " + oldVersion + " -> New Version: " + fields[VersionProperty]);
				}
			}

			try
			{
				IDbCommand statement = useBatch
				                       	? session.Batcher.PrepareBatchCommand(sql.CommandType, sql.Text, sql.ParameterTypes)
				                       	: session.Batcher.PrepareCommand(sql.CommandType, sql.Text, sql.ParameterTypes);
				try
				{
					int index = 0;

					//index += expectation.Prepare(statement, factory.ConnectionProvider.Driver);
					index = Dehydrate(id, fields, includeProperty, propertyColumnUpdateable, j, statement, session, index);

					// Write any appropriate versioning conditional parameters
					if (useVersion && OptimisticLockMode == OptimisticLockMode.Version)
					{
						VersionType.NullSafeSet(statement, oldVersion, index, session);
					}
					else if (OptimisticLockMode.Version < OptimisticLockMode && null != oldFields)
					{
						bool[] versionability = PropertyVersionability;
						bool[] includeOldField = OptimisticLockMode == OptimisticLockMode.All
						                         	? PropertyUpdateability
						                         	: includeProperty;

						for (int i = 0; i < entityMetamodel.PropertySpan; i++)
						{
							bool include = includeOldField[i] &&
							               IsPropertyOfTable(i, j) &&
							               versionability[i];
							if (include)
							{
								if (!PropertyTypes[i].IsDatabaseNull(oldFields[i]))
								{
									PropertyTypes[i].NullSafeSet(statement, oldFields[i], index, session);
									index += GetPropertyColumnSpan(i);
								}
							}
						}
					}

					if (useBatch)
					{
						session.Batcher.AddToBatch(expectation);
					}
					else
					{
						Check(session.Batcher.ExecuteNonQuery(statement), id, j, expectation, statement);
					}
				}
				catch (Exception e)
				{
					if (useBatch)
					{
						session.Batcher.AbortBatch(e);
					}

					throw;
				}
				finally
				{
					if (!useBatch)
					{
						session.Batcher.CloseCommand(statement, null);
					}
				}
			}
			catch (HibernateException)
			{
				// Do not call Convert on HibernateExceptions
				throw;
			}
			catch (Exception sqle)
			{
				throw Convert(sqle, "could not update: " + MessageHelper.InfoString(this, id), sql.Text);
			}
//.........這裏部分代碼省略.........
開發者ID:Novthirteen,項目名稱:sconit_timesseiko,代碼行數:101,代碼來源:AbstractEntityPersister.cs

示例12: Append

		public virtual void Append(SqlCommandInfo commandInfo)
		{
			resultSetsCount++;
			sqlString = sqlString.Append(commandInfo.Text).Append(";").Append(Environment.NewLine);
			types.AddRange(commandInfo.ParameterTypes);
		}
開發者ID:pontillo,項目名稱:PowerNap,代碼行數:6,代碼來源:BasicResultSetsCommand.cs

示例13: Prepare

			protected internal override IDbCommand Prepare(SqlCommandInfo insertSQL, ISessionImplementor session)
			{
				return session.Batcher.PrepareCommand(CommandType.Text, insertSQL.Text, insertSQL.ParameterTypes);
			}
開發者ID:jlevitt,項目名稱:nhibernate-core,代碼行數:4,代碼來源:IdentityGenerator.cs

示例14: AbstractCollectionPersister


//.........這裏部分代碼省略.........

				CheckColumnDuplication(distinctColumns, idColl.Identifier.ColumnIterator);
			}
			else
			{
				identifierType = null;
				identifierColumnName = null;
				identifierColumnAlias = null;
				identifierGenerator = null;
				identityDelegate = null;
			}

			#endregion

			#region GENERATE THE SQL

			// NH Different behavior : for the Insert SQL we are managing isPostInsertIdentifier (not supported in H3.2.5) 
			if (collection.CustomSQLInsert == null)
			{
				if (!IsIdentifierAssignedByInsert)
				{
					sqlInsertRowString = GenerateInsertRowString();
				}
				else
				{
					sqlInsertRowString = GenerateIdentityInsertRowString();
				}
				insertCallable = false;
				insertCheckStyle = ExecuteUpdateResultCheckStyle.Count;
			}
			else
			{
				SqlType[] parmsTypes = GenerateInsertRowString().ParameterTypes;
				sqlInsertRowString = new SqlCommandInfo(collection.CustomSQLInsert, parmsTypes);
				insertCallable = collection.IsCustomInsertCallable;
				insertCheckStyle = collection.CustomSQLInsertCheckStyle
				                   ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLInsert, insertCallable);
			}

			sqlUpdateRowString = GenerateUpdateRowString();
			if (collection.CustomSQLUpdate == null)
			{
				updateCallable = false;
				updateCheckStyle = ExecuteUpdateResultCheckStyle.Count;
			}
			else
			{
				sqlUpdateRowString = new SqlCommandInfo(collection.CustomSQLUpdate, sqlUpdateRowString.ParameterTypes);
				updateCallable = collection.IsCustomUpdateCallable;
				updateCheckStyle = collection.CustomSQLUpdateCheckStyle
				                   ?? ExecuteUpdateResultCheckStyle.DetermineDefault(collection.CustomSQLUpdate, updateCallable);
			}

			sqlDeleteRowString = GenerateDeleteRowString();
			if (collection.CustomSQLDelete == null)
			{
				deleteCallable = false;
				deleteCheckStyle = ExecuteUpdateResultCheckStyle.None;
			}
			else
			{
				sqlDeleteRowString = new SqlCommandInfo(collection.CustomSQLDelete, sqlDeleteRowString.ParameterTypes);
				deleteCallable = collection.IsCustomDeleteCallable;
				deleteCheckStyle = ExecuteUpdateResultCheckStyle.None;
			}
開發者ID:khaliyo,項目名稱:Spring.net-NHibernate.net-Asp.net-MVC-DWZ-,代碼行數:66,代碼來源:AbstractCollectionPersister.cs

示例15: Update

        public void Update(object id, object[] fields, int[] dirtyFields, bool hasDirtyCollection,
			object[] oldFields, object oldVersion, object obj, object rowId, ISessionImplementor session)
        {
            //note: dirtyFields==null means we had no snapshot, and we couldn't get one using select-before-update
            //	  oldFields==null just means we had no snapshot to begin with (we might have used select-before-update to get the dirtyFields)

            bool[] tableUpdateNeeded = GetTableUpdateNeeded(dirtyFields, hasDirtyCollection);
            int span = TableSpan;
            bool[] propsToUpdate;
            SqlCommandInfo[] updateStrings;

            if (entityMetamodel.IsDynamicUpdate && dirtyFields != null)
            {
                // For the case of dynamic-update="true", we need to generate the UPDATE SQL
                propsToUpdate = GetPropertiesToUpdate(dirtyFields, hasDirtyCollection);
                // don't need to check laziness (dirty checking algorithm handles that)
                updateStrings = new SqlCommandInfo[span];
                for (int j = 0; j < span; j++)
                {
                    updateStrings[j] = tableUpdateNeeded[j]
                                                            ? GenerateUpdateString(propsToUpdate, j, oldFields, j == 0 && rowId != null)
                                                            : null;
                }
            }
            else
            {
                // For the case of dynamic-update="false", or no snapshot, we use the static SQL
                updateStrings = GetUpdateStrings(rowId != null, HasUninitializedLazyProperties(obj, session.EntityMode));
                propsToUpdate = GetPropertyUpdateability(obj, session.EntityMode);
            }

            for (int j = 0; j < span; j++)
            {
                // Now update only the tables with dirty properties (and the table with the version number)
                if (tableUpdateNeeded[j])
                {
                    UpdateOrInsert(id, fields, oldFields, j == 0 ? rowId : null, propsToUpdate, j, oldVersion, obj, updateStrings[j], session);
                }
            }
        }
開發者ID:aistrate,項目名稱:TypingPracticeTexts,代碼行數:40,代碼來源:AbstractEntityPersister.cs


注:本文中的NHibernate.SqlCommand.SqlCommandInfo類示例由純淨天空整理自Github/MSDocs等開源代碼及文檔管理平台,相關代碼片段篩選自各路編程大神貢獻的開源項目,源碼版權歸原作者所有,傳播和使用請參考對應項目的License;未經允許,請勿轉載。