Avatar billede tomjelen Nybegynder
25. marts 2004 - 10:28 Der er 6 kommentarer og
1 løsning

større Stored Procedure problem

Vi har en række små stored procedures der skal køres fra en metode, det fungere fint fra c#, men ville gerne have det banket sammen til en stored procedure. Jeg skal i en bug tabel tilføje en bug, hvis der er nogle billed attachments til denne bug, så skal dette array af attachments tilføjes i en bugAttachment tabel, hvor en af kolonnerne er det BugID identity som blev lavet da vi tilføjet buggen. Hvis noget i denne process fejler vil vi ikke have det commit'et, og vi vil meget gerne vide over i vores c# kode om proceduren fejlede eller ej.

Min C# metode ser sådan her ud:

public bool addBug(int btid,string bdesc,int pid,int cid, byte[][] attach)
{
    bool check=true;

    try
    {
        conn.Open();
    }
    catch(Exception e)
    {
        Console.WriteLine(e.ToString());
        conn.Close();
        check=false;
        return check;
    }
    //Starting a Transaction to make it possible to commit/rollback
    //if any parts of the method fails
    OleDbTransaction trans = conn.BeginTransaction();
    try
    {
        //Adding bug info to the tblBug table
        OleDbCommand cmd = new OleDbCommand("addBug", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("@BugTypeID", OleDbType.Integer).Value=btid;
        cmd.Parameters.Add("@BugDescription", OleDbType.VarChar).Value=bdesc;
        cmd.Parameters.Add("@BugDescReply", OleDbType.VarChar).Value=DBNull.Value;
        cmd.Parameters.Add("@BugStatusID", OleDbType.Integer).Value=1;
        cmd.Parameters.Add("@BugReportDate", OleDbType.DBTimeStamp).Value=DateTime.Now;
        cmd.Parameters.Add("@BugFixedDate", OleDbType.DBTimeStamp).Value=DBNull.Value;
        cmd.Parameters.Add("@BughandlerID", OleDbType.Integer).Value=1;
        cmd.Parameters.Add("@ProjectID", OleDbType.Integer).Value=pid;
        cmd.Parameters.Add("@CustomerID", OleDbType.Integer).Value=cid;
        cmd.Parameters.Add("@BugAttachmentCount", OleDbType.Integer).Value=0;
        cmd.Transaction = trans;
        cmd.ExecuteNonQuery();
        //Retrieves the last generated identity, which is the BugID generated above
        cmd = new OleDbCommand("SELECT @@IDENTITY",conn);//XXXXX
        cmd.Transaction = trans;
        OleDbDataReader dbReader = cmd.ExecuteReader();
        dbReader.Read();
        int bugID = Convert.ToInt32(dbReader.GetValue(0));
        dbReader.Close();
        //Adds the array of attachments to the database
       
        if(attach!=null)
        {
            for(int index=0;index<attach.Length;index++)
            {
                cmd = new OleDbCommand("addAttachment", conn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("@BugTypeID", OleDbType.Integer).Value=bugID;
                cmd.Parameters.Add("@BugAttachment", OleDbType.VarBinary, attach[index].Length).Value = attach[index];
                Console.WriteLine(index);
                cmd.Transaction = trans;
                cmd.ExecuteNonQuery();
            }
        }
        //Commits the transaction if everything was succesful
        trans.Commit();
    }
    //the transactions rolls back if anything fails
    catch(Exception e)
    {
        Console.WriteLine("Exception caught in AddBug()\n"+e.Message+"\n\n"+e.ToString());
        check=false;
        trans.Rollback();
    }
    finally
    {
        conn.Close();
    }
    return check;
}

De to stored procedures denne metode kører ser sådan ud:

CREATE PROCEDURE addBug @BugTypeID integer, @BugDescription text, @BugDescReply text, @BugStatusID integer, @BugReportDate smalldatetime, @BugFixedDate smalldatetime, @BughandlerID integer, @ProjectID integer, @CustomerID integer, @BugAttachmentCount integer
AS
INSERT INTO tblBugs VALUES(@BugTypeID, @BugDescription, @BugDescReply, @BugStatusID, @BugReportDate, @BugFixedDate, @BughandlerID, @ProjectID, @CustomerID, @BugAttachmentCount)
------

CREATE PROCEDURE addAttachment @BugID integer, @BugAttachment Image
AS
INSERT INTO tblBugAttachments VALUES(@BugID, @BugAttachment)
UPDATE tblBugs
    SET BugAttachmentCount = BugAttachmentCount+1
    WHERE BugID=@BugID
GO

Mine problemer er så:
- Hvordan returnere jeg en boolean værdi der fortæller om det hele gik godt eller ej
- Hvordan får vi vores stored procedure til at tage et byte[][] som parameter

Stil spørgsmål hvis forklaringen ikke er helt klar
Avatar billede trer Nybegynder
25. marts 2004 - 10:33 #1
create procedure addattachemnt (addAttachment @BugID integer, @BugAttachment Image)
as
begin
  declare @e int
  set @e = 0
  set xact_abort on  -- rollback ved fejl
  begin transaction
  insert into ... 
  set @e = @e + @@error
  update ...
  set @e = @e + @@error
  if @e=0 begin
    commit transaction
  end else begin
    rollback transaction
  end
  return @e
end
go

du kan umiddelbart ikke sætte et bytearray som parameter til en sp - muligvis kan du benytte en tablevariabel - men det har jeg aldrig set/prøvet.  check books online om der skulle stå noget...

jeg ville nok vælge at benytte en varbinary til at indeholde et bytearray - du kan så trække de enkelte stumper ud via en SUBSTRING() i din sp.
Avatar billede tomjelen Nybegynder
25. marts 2004 - 10:48 #2
Mener du at skifte vores Image type ud med varbinary?

Af hvad jeg kan se kan der max være 8000bytes i en varbinary, vi skal bruge en del mere til at gemme billed attachments
Avatar billede trer Nybegynder
25. marts 2004 - 11:06 #3
Nej, jeg havde misforstået brugen af arrayet. Så er eneste mulighed at lave gentagne parametre med default værdier a la dette

create procedure addattach (@bugid, @bugatt1 image = null, @bugatt2 image = null, @bugatt3 image = null,,,,@bugatt8 image = null)

if not isnull(@bugatt1) insert into ..
if not isnull(@bugatt2) insert into ..

-> det kan nok optimeres lidt :-)
Avatar billede tomjelen Nybegynder
25. marts 2004 - 12:22 #4
hmm, jeg ved jo ikke helt hvor mange af de her attachments jeg har. Så dit forslag er at tilføje så mange image parametre som jeg tror jeg max får af attachments nogensinde?
Avatar billede trer Nybegynder
25. marts 2004 - 12:51 #5
Ja. Ikke særlig optimalt, men brugbart.

En bedre løsning ville nok være at kalde addattachment() fra dit C# program så mange gange som du har bilag.
Avatar billede tomjelen Nybegynder
25. marts 2004 - 15:26 #6
Ja, så er jeg bare lidt tilbage til hvad jeg startede med. Grunden til at jeg gerne vil have hele lortet ind i en SP, er fordi det virker pænere.
Avatar billede trer Nybegynder
25. marts 2004 - 20:14 #7
Vi er ikke uenige - men T-SQL har desværre nogle seriøse begrænsninger i forhold til det skulle være et prof. sprog - f.eks. ville en fejlhåndtering baseret på exception handling (som man har i Oracle) være en del pænere end at skulle summe en fejlstatus op ved gentagne check på @@error ...

Men sådan er livet - og SQL Server :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester