private IEnumerable <IEnumerable <IDataRow> > ExecuteResult(object args, PpsDataTransactionExecuteBehavior behavior) { transaction.ResetTransaction(); return(ExecuteResultCore(args, behavior)); } // func ExecuteResult
} // proc Dispose #endregion #region -- Execute Result ----------------------------------------------------- /// <summary>Overwrite to execute command.</summary> /// <param name="args">Arguments for the command</param> /// <param name="behavior">Result behaviour.</param> /// <returns></returns> protected abstract IEnumerable <IEnumerable <IDataRow> > ExecuteResultCore(object args, PpsDataTransactionExecuteBehavior behavior);
} // func CopyData private IEnumerable <IEnumerable <IDataRow> > UpdateRevisionData(object _args, PpsDataTransactionExecuteBehavior behavior) { // function to update revision // UpdateRevision(long ObjkId, long RevId, long ParentId, long CreateUserId, [opt] date CreateDate, bool Deflate, bool IsDocumentText) // read arguments var args = (LuaTable)_args; var objkId = args.GetOptionalValue("ObjkId", -1L); if (objkId < 0) { throw new ArgumentOutOfRangeException("ObjkId", objkId, "ObjkId is mising."); } var revId = args.GetOptionalValue("RevId", -1L); var parentRevId = args.GetOptionalValue("ParentRevId", -1L); var createUserId = args.GetOptionalValue("CreateUserId", 0L); var createDate = args.GetOptionalValue("CreateDate", DateTime.Now); var isDocumentText = args.GetOptionalValue("IsDocumentText", false); var shouldDeflate = args.GetOptionalValue("Deflate", false); var srcStream = (Stream)args.GetMemberValue("Content"); // get source stream long documentId = -1; // read first block var buf = new byte[0x80000]; var readed = ReadStreamData(srcStream, buf); var integratedUser = Credentials as PpsIntegratedCredentials; var useFileStream = readed >= buf.Length; if (useFileStream) // inline data in revision { if (integratedUser != null) { #region -- insert into objf -- using (integratedUser.Impersonate()) using (var cmd = CreateCommand(CommandType.Text, false)) { cmd.CommandText = "INSERT INTO dbo.[ObjF] ([HashAlgo], [Hash], [Data]) " + "OUTPUT inserted.Id, inserted.Data.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() " + "VALUES ('SHA2_256', 0x, 0x);"; using (var r = (SqlDataReader)cmd.ExecuteReaderEx(CommandBehavior.SingleRow)) { if (r.Read()) { // get destination file documentId = r.GetInt64(0); var path = r.GetString(1); var context = r.GetSqlBytes(2).Buffer; using (var dstFileStream = new SqlFileStream(path, context, FileAccess.Write)) { var(hashName, hashValue) = CopyData(shouldDeflate, srcStream, buf, readed, dstFileStream); args["HashValue"] = hashValue; args["HashAlgo"] = hashName; } } else { throw new Exception("Insert FileStream failed."); } } } #endregion #region -- update objf -- using (var cmd = CreateCommand(CommandType.Text, false)) { cmd.CommandText = "UPDATE dbo.[ObjF] SET [HashAlgo] = @HashAlgo, [Hash] = @HashValue WHERE [Id] = @DocumentId;"; cmd.Parameters.Add("@HashValue", SqlDbType.VarBinary).Value = args["HashValue"]; cmd.Parameters.Add("@HashAlgo", SqlDbType.VarChar).Value = args["HashAlgo"]; cmd.Parameters.Add("@DocumentId", SqlDbType.BigInt).Value = documentId; cmd.ExecuteNonQueryEx(); } #endregion } else { #region -- insert into obf -- using (var cmd = CreateCommand(CommandType.Text, false)) { cmd.CommandText = "INSERT INTO dbo.[ObjF] ([HashAlgo], [Hash], [Data]) " + "OUTPUT inserted.Id " + "VALUES (@HashAlgo, @HashValue, @Data);"; using (var dstMem = new MemoryStream()) { var(hashName, hashValue) = CopyData(shouldDeflate, srcStream, buf, readed, dstMem); cmd.Parameters.Add("@HashValue", SqlDbType.VarBinary).Value = hashValue; cmd.Parameters.Add("@HashAlgo", SqlDbType.VarChar).Value = hashName; cmd.Parameters.Add("@Data", SqlDbType.VarBinary).Value = dstMem.ToArray(); } using (var r = (SqlDataReader)cmd.ExecuteReaderEx(CommandBehavior.SingleRow)) { if (r.Read()) { documentId = r.GetInt64(0); } else { throw new Exception("Insert FileStream failed."); } } } #endregion } } else { #region -- build buf -- if (shouldDeflate) // deflate buffer { using (var dstMem = new MemoryStream()) using (var dst = new GZipStream(dstMem, CompressionMode.Compress)) { dst.Write(buf, 0, readed); dst.Dispose(); dstMem.Flush(); buf = dstMem.ToArray(); } } else // create simple byte-array { var newBuf = new byte[readed]; Array.Copy(buf, 0, newBuf, 0, readed); buf = newBuf; } #endregion } // write table or update revision using (var cmd = CreateCommand(CommandType.Text, false)) { if (revId < 0) // always insert { cmd.CommandText = "INSERT INTO dbo.[ObjR] ([ObjkId], [ParentId], [IsDocumentText], [IsDocumentDeflate], [Document], [DocumentId], [DocumentLink], [CreateDate], [CreateUserId]) " + "OUTPUT inserted.[Id] " + " VALUES (@ObjkId, @ParentId, @IsDocumentText, @IsDocumentDeflate, @Document, @DocumentId, NULL, @CreateDate, @CreateUserId);"; } else // merge this rev { cmd.CommandText = "MERGE INTO dbo.[ObjR] as dst" + "USING (SELECT @ObjkId, @RevId, @IsDocumentText, @IsDocumentDeflate, @Document, @DocumentId, @CreateDate, @CreateUserId) as src (NewObjkId, NewRevId, NewIsDocumentText, NewIsDocumentDeflate, NewDocument, NewDocumentId, NewCreateDate, NewCreateUserId) " + "ON (dst.ObjkId = src.NewObjkId AND dst.Id = src.NewRevId) " + "WHEN MATCHED THEN" + "UPDATE SET [IsDocumentText] = src.NewIsDocumentText, [IsDocumentDeflate] = src.NewIsDocumentDeflate, [Document] = src.NewDocument, [CreateDate] = src.NewCreateDate, [CreateUserId] = src.NewCreateUserId" + "WHEN NOT MATCHED THEN " + "INSERT ([ObjkId], [IsDocumentText], [IsDocumentDeflate], [Document], [DocumentId], [DocumentLink], [CreateDate], [CreateUserId]) " + " VALUES (src.NewObjkId, src.NewIsDocumentText, src.NewIsDocumentDeflate, src.NewDocument, src.NewDocumentId, NULL, src.NewCreateDate, src.NewCreateUserId)" + "OUTPUT inserted.Id"; cmd.Parameters.Add("@RevId", SqlDbType.BigInt).Value = revId; } cmd.Parameters.Add("@ObjkId", SqlDbType.BigInt).Value = objkId; cmd.Parameters.Add("@ParentId", SqlDbType.BigInt).Value = parentRevId <= 0 ? (object)DBNull.Value : parentRevId; cmd.Parameters.Add("@IsDocumentText", SqlDbType.Bit).Value = isDocumentText; cmd.Parameters.Add("@IsDocumentDeflate", SqlDbType.Bit).Value = shouldDeflate; cmd.Parameters.Add("@Document", SqlDbType.VarBinary).Value = useFileStream ? (object)DBNull.Value : buf; cmd.Parameters.Add("@DocumentId", SqlDbType.BigInt).Value = useFileStream ? documentId : (object)DBNull.Value; cmd.Parameters.Add("@CreateDate", SqlDbType.DateTime2).Value = createDate; cmd.Parameters.Add("@CreateUserId", SqlDbType.BigInt).Value = createUserId; using (var r = (SqlDataReader)cmd.ExecuteReaderEx(CommandBehavior.SingleRow)) { if (r.Read()) { args["RevId"] = r.GetInt64(0); } else { throw new InvalidOperationException("Merge/Insert failed."); } } } yield break; } // proc UpdateRevisionData
} // ctor /// <summary></summary> /// <param name="args"></param> /// <param name="behavior"></param> /// <returns></returns> protected override IEnumerable <IEnumerable <IDataRow> > ExecuteResultCore(object args, PpsDataTransactionExecuteBehavior behavior) => invoke.Invoke(args, behavior);
} // proc UpdateRevisionData #endregion #region -- GetRevisionData ------------------------------------------------ private IEnumerable <IEnumerable <IDataRow> > GetRevisionData(object _args, PpsDataTransactionExecuteBehavior behavior) { // function to get revision data // GetRevisionData(long ObjkId oder long RevId) var args = (LuaTable)_args; var revId = args.GetOptionalValue("RevId", -1L); var objkId = args.GetOptionalValue("ObjkId", -1L); if (revId <= 0 && objkId <= 0) { throw new ArgumentException("Invalid arguments.", "revId|objkId"); } using (var cmd = CreateCommand(CommandType.Text, false)) { var useFileStream = Credentials is PpsIntegratedCredentials; // only integrated credentials can use filestream cmd.CommandText = "SELECT [IsDocumentText], [IsDocumentDeflate], [Document], [DocumentId], [DocumentLink], [HashAlgo], [Hash], " + (useFileStream ? "[Data].PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() " : "[Data] ") + (revId > 0 ? "FROM dbo.[ObjR] r LEFT OUTER JOIN dbo.[ObjF] f ON (r.[DocumentId] = f.[Id]) WHERE r.[Id] = @Id;" : "FROM dbo.[ObjK] o INNER JOIN dbo.[ObjR] r ON (o.HeadRevId = r.[Id]) LEFT OUTER JOIN dbo.[ObjF] f ON (r.[DocumentId] = f.[Id]) WHERE o.[Id] = @Id;" ); cmd.Parameters.Add("@Id", SqlDbType.BigInt).Value = revId > 0 ? revId : objkId; using (var r = (SqlDataReader)cmd.ExecuteReaderEx(CommandBehavior.SingleRow)) { if (!r.Read()) { yield break; } var hashAlgo = r.IsDBNull(5) ? null : r.GetString(5); var hashValue = r.IsDBNull(6) ? null : r.GetSqlBytes(6).Buffer; // convert stream var isDocumentDeflated = r.GetBoolean(1); Stream src; if (!r.IsDBNull(7)) // file stream or bytes { if (useFileStream) { using (((PpsIntegratedCredentials)Credentials).Impersonate()) src = new SqlFileStream(r.GetString(7), r.GetSqlBytes(8).Buffer, FileAccess.Read); } else { src = r.GetSqlBytes(7).Stream; } } else if (!r.IsDBNull(2)) // inline content { src = r.GetSqlBytes(2).Stream; } else if (!r.IsDBNull(3)) // linked content { src = new FileStream(r.GetString(3), FileMode.Open, FileAccess.Read); } else // no content { src = null; } if (src != null && isDocumentDeflated) { src = new GZipStream(src, CompressionMode.Decompress, false); } // return result yield return(new IDataRow[] { new SimpleDataRow( new object[] { r.GetBoolean(0), src, hashAlgo, hashValue }, new SimpleDataColumn[] { new SimpleDataColumn("IsDocumentText", typeof(bool)), new SimpleDataColumn("Document", typeof(Stream)), new SimpleDataColumn("HashAlgo", typeof(string)), new SimpleDataColumn("Hash", typeof(byte[])) } ) }); } } } // proc GetRevisionData