none
Insertar Maestro Detalle en c# con XMl RRS feed

  • Pregunta

  • amigos tengo ese problema que no se como pasar el archivo xml al procedimiento almancenado.

    el xml lo genero con este codigo

    protected void BtonRegistrarOferta_Click(object sender, EventArgs e)
            { 
                string path = Server.MapPath("~/OfertaMarcas.xml");
                using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
                {
                    writer.Formatting = Formatting.Indented;
    
                    writer.WriteStartDocument();
                    writer.WriteStartElement("ROOt");
                    writer.WriteStartElement("OfertaEcoTec");
                    writer.WriteAttributeString("USUARIOID", (Convert.ToString(Session["IdUsuario"]);
                    writer.WriteAttributeString("LICITACIONID", Convert.ToString(this.ddLicitacion.SelectedValue));
                    writer.WriteAttributeString("PROVEEDORID", Convert.ToString(this.lblProveedorId.Text));
                    writer.WriteAttributeString("REQID", Convert.ToString(this.ddclave.SelectedValue));
                    writer.WriteAttributeString("GPO", Convert.ToString(this.txtgpo.Text));
                    writer.WriteAttributeString("GEN", Convert.ToString(this.txtgen.Text));
                    writer.WriteAttributeString("ESP", Convert.ToString(this.txtesp.Text));
                    writer.WriteAttributeString("DIF", Convert.ToString(this.txtdif.Text));
                    writer.WriteAttributeString("VAR", Convert.ToString(this.txtvar.Text));
                    writer.WriteAttributeString("PRECIOOFER",this.txtofertado.Text);
                    writer.WriteAttributeString("DESCUENTOOFER", Convert.ToString(this.txtdescuento.Text));
                    writer.WriteAttributeString("PRECIONETO", Convert.ToString(this.txtdescuento.Text));
                    writer.WriteAttributeString("CANTMAXOFER", Convert.ToString(this.txtmaxofer.Text));              
    
                    //foreach (GridViewRow row in this.GridMarcas.Rows)
                    foreach (GridViewRow row in GridMarcas.Rows)
                    {
                        writer.WriteStartElement("MARCASOFER");
    
    
                        Label MARCA = (Label)row.FindControl("lblItemClase");
                        Label OFICIO = (Label)row.FindControl("lblItemOficio");
                        Label INCLUSION = (Label)row.FindControl("lblItemTramite");
                        Label ORIGEN = (Label)row.FindControl("lblOrigen");
                        Label FABRICANTE = (Label)row.FindControl("lblItemFabricante");
                        Label RFCFAB = (Label)row.FindControl("lblItemRfc");                                     
    
                        writer.WriteAttributeString("MARCA",HttpUtility.HtmlEncode( MARCA.Text));
                        writer.WriteAttributeString("OFICIO", HttpUtility.HtmlEncode(OFICIO.Text));
                        writer.WriteAttributeString("INCLUSION", HttpUtility.HtmlEncode(INCLUSION.Text));
                        writer.WriteAttributeString("ORIGEN", HttpUtility.HtmlEncode(ORIGEN.Text));
                        writer.WriteAttributeString("FABRICANTE", HttpUtility.HtmlEncode(FABRICANTE.Text));
                        writer.WriteAttributeString("RFCFAB", HttpUtility.HtmlEncode(RFCFAB.Text));
    
                        writer.WriteEndElement();
                    }
    
                    
                    writer.WriteEndElement();                
    
                    writer.Close();
                }
            }

    ahora como le hago para pasar este archivo al procedimiento almacenado.

    y poder guardarlo en las tablas definitivas.

    muchas gracias.


    Horacio Xochitemol Bautista

    jueves, 10 de septiembre de 2015 0:05

Respuestas

  • Gracias amigo ya lo pude pasarlo al SP; ahora bien en mi tabla tengo columnas que debe ser unicas; el SP no inserta la informacion en la tabla 1(columnas con campos unicos)  pero si en la tabla 2, es decir no captura el error podrian echarme una mano por favor el SP es el siguiente.

    USE [MCCUR]
    GO
    /****** Object:  StoredProcedure [dbo].[PGUARDA_OFERTA_ECO_MAESTRO_DETALLE]    Script Date: 10/09/2015 06:18:04 p.m. ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER Procedure [dbo].[PGUARDA_OFERTA_ECO_MAESTRO_DETALLE]
    @xml text
    as
    DECLARE @hDoc int
    
    Begin TRANSACTION
    
    DECLARE @Error int
    	EXEC sp_xml_preparedocument @hDoc OUTPUT, @xml
    	Declare @IdOferta int
    	Insert into OFERTAS (USUARIOID,LICITACIONID,MREQUERIMIENTOID,PROVEEDORID,GPO,GEN,ESP,DIF,VAR,PRECIO_OFERTADO,CANT_MAX,DESCUENTO,PRECIO_NETO)	
    	SELECT * FROM OPENXML(@hDoc, N'/ROOT/OfertaEcoTec') with (USUARIOID INT,LICITACIONID int,REQID int, PROVEEDORID int,GPO char(3),GEN char(3),ESP char(4),DIF char(2),[VAR] char(2),PRECIOOFER float,CANTMAXOFER int,DESCUENTOOFER float,PRECIONETO float)
    	Select @IdOferta =@@identity
    	--almacendo el error  por si no se ejecuta la instruccion correctamente
    	SET @Error=@@ERROR
    	--si la variable de error es diferente de cero ejecuto el codigo para cancelar la transaccion
    	if (@Error<>0) GOTO TratarError
    	   --si el primer inset se realiza con exito pasamos al segundo insert de marcas
    		Insert into MARC_OFERT (OFERTAID,MARCA,OFICIO_EXIME,TRAMITE_INCLUSION,ORIGEN,FABRICANTE,RFC_FABRICANTE)		
    		SELECT @IdOferta,* FROM OPENXML(@hDoc, N'/ROOT/OfertaEcoTec/MARCASOFER') with (MARCA VARCHAR(200),OFICIO VARCHAR(200), INCLUSION VARCHAR(200), ORIGEN VARCHAR(200),FABRICANTE VARCHAR(200),RFCFAB VARCHAR(30))
    		EXEC sp_xml_removedocument @hDoc
    	    
    		SET @Error=@@ERROR
        if (@Error<>0)  GOTO TratarError
    		
    		COMMIT TRANSACTION	 
    		
    TratarError: 
     if @@ERROR <>0 
      BEGIN
    	PRINT 'Ocurrio un error durante la transaccion'
    	ROLLBACK TRANSACTION
      END
    


    Horacio Xochitemol Bautista

    • Marcado como respuesta Xochitemol martes, 15 de septiembre de 2015 0:36
    viernes, 11 de septiembre de 2015 14:39

Todas las respuestas

  • Hola Horacio,

    Para pasar un XML a un procedimiento almacenado como parámetro, en primer lugar debes definir el procedimiento para recibir un parámetro de tipo XML.

    CREATE PROCEDURE [dbo].[XYZ] 
    
    @xml XML
    
    AS
    
    BEGIN
       ...
    END

    Una vez definido el procedimiento, el proceso para enviar el XML en C# es muy similar al envío de cualquier otro parámetro. Puedes probar lo siguiente:

    //Leemos el contenido del fichero en una variable
    var xml = File.ReadAllText(path);
    
    //Creamos la conexión y el comando
    using (SqlConnection con = new SqlConnection(ConnStr))
    {
            using (SqlCommand cmd = new SqlCommand("XYZ"))
            {
    	    //Asignamos la conexión y pasamos el parámetro
    	    cmd.Connection = con;
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@xml", xml);
                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();
            }
    }

    Para más información echa un vistazo a los siguientes enlaces:

    http://www.codeproject.com/Questions/209223/Passing-XML-to-stored-procedure

    http://stackoverflow.com/questions/3600091/how-to-pass-xml-from-c-sharp-to-a-stored-procedure-in-sql-server-2008

    http://www.aspsnippets.com/Articles/Pass-XML-parameter-to-Stored-Procedure-in-C-and-VBNet.aspx

    Un saludo.


    When an answer is helpful, please vote as helpful, propose as answer and/or mark as answer

    jueves, 10 de septiembre de 2015 6:26
  • Gracias por la pronta respuesta, pero tengo una duda aquí genero el xml en un archivo de la aplicación; que pasaría con el archivo xml si están 2 o mas usuarios usando la aplicación en el mismo Proceso?; seria mejor guardar el archivo xml en una variable de tipo texto para después pasarla como parámetro al SP; como guardo ese archivo en la una variable de tipo string?

    por su ayuda muchas gracias.


    Horacio Xochitemol Bautista

    jueves, 10 de septiembre de 2015 15:21
  • Haber amigos no he podido mandar el xml como parámetroal SP hice algunas modificaciones al codigo y quedo de la siguiente manera.

    para generar el xml y pasarlo al sp.

    protected void BtonRegistrarOferta_Click(object sender, EventArgs e)
            {
                using (StringWriter str = new StringWriter())
                using (XmlTextWriter writer = new XmlTextWriter(str))
                {
                    writer.Formatting = Formatting.Indented;
    
                    writer.WriteStartDocument();
                    writer.WriteStartElement("ROOT");
                    writer.WriteStartElement("OfertaEcoTec");
                    writer.WriteAttributeString("USUARIOID", (Convert.ToString(Session["IdUsuario"])));
                    writer.WriteAttributeString("LICITACIONID", Convert.ToString(this.ddLicitacion.SelectedValue));
                    writer.WriteAttributeString("REQID", Convert.ToString(this.ddclave.SelectedValue));
                    writer.WriteAttributeString("PROVEEDORID", Convert.ToString(this.lblProveedorId.Text));               
                    writer.WriteAttributeString("GPO", Convert.ToString(this.txtgpo.Text));
                    writer.WriteAttributeString("GEN", Convert.ToString(this.txtgen.Text));
                    writer.WriteAttributeString("ESP", Convert.ToString(this.txtesp.Text));
                    writer.WriteAttributeString("DIF", Convert.ToString(this.txtdif.Text));
                    writer.WriteAttributeString("VAR", Convert.ToString(this.txtvar.Text));
                    writer.WriteAttributeString("PRECIOOFER",this.txtofertado.Text);
                    writer.WriteAttributeString("DESCUENTOOFER", Convert.ToString(this.txtdescuento.Text));
                    writer.WriteAttributeString("PRECIONETO", Convert.ToString(this.txtdescuento.Text));
                    writer.WriteAttributeString("CANTMAXOFER", Convert.ToString(this.txtmaxofer.Text));              
    
                    //foreach (GridViewRow row in this.GridMarcas.Rows)
                    foreach (GridViewRow row in GridMarcas.Rows)
                    {
                        writer.WriteStartElement("MARCASOFER");
    
    
                        Label MARCA = (Label)row.FindControl("lblItemClase");
                        Label OFICIO = (Label)row.FindControl("lblItemOficio");
                        Label INCLUSION = (Label)row.FindControl("lblItemTramite");
                        Label ORIGEN = (Label)row.FindControl("lblOrigen");
                        Label FABRICANTE = (Label)row.FindControl("lblItemFabricante");
                        Label RFCFAB = (Label)row.FindControl("lblItemRfc");                                     
    
                        writer.WriteAttributeString("MARCA",HttpUtility.HtmlEncode( MARCA.Text).Trim());
                        writer.WriteAttributeString("OFICIO", HttpUtility.HtmlEncode(OFICIO.Text).Trim());
                        writer.WriteAttributeString("INCLUSION", HttpUtility.HtmlEncode(INCLUSION.Text).Trim());
                        writer.WriteAttributeString("ORIGEN", HttpUtility.HtmlEncode(ORIGEN.Text).Trim());
                        writer.WriteAttributeString("FABRICANTE", HttpUtility.HtmlEncode(FABRICANTE.Text).Trim());
                        writer.WriteAttributeString("RFCFAB", HttpUtility.HtmlEncode(RFCFAB.Text).Trim());
    
                        writer.WriteEndElement();
                    }                
                    writer.WriteEndElement();                
                    writer.Close();
                    Response.Write(str);
    
                    //conexion a la base de datos
                    conexion cn = new conexion();
                    // SqlConnection cnx = cn.conectar();
    
                    using (SqlConnection cnx = cn.conectar())
                    {
                        using (SqlCommand cmd = new SqlCommand("RegistroOfertaEcoTec"))
                        {
                            try
                            {//Asignamos la conexión y pasamos el parámetro
                                cmd.Connection = cnx;
                                cmd.Parameters.AddWithValue("@xml", str);
                                cmd.CommandType = CommandType.StoredProcedure;
                                cnx.Open();
                                cmd.ExecuteNonQuery();
                                cnx.Close();
                            }
                            catch (Exception Err)
                            {
                                errorgral = Err.Message.ToString() + " - " + Err.Source.ToString();
                                MessageBoxShow(this, errorgral);
                            }
                        }
                    }
                }            
            }


    ahora el procedimiento almacenado

    alter Procedure RegistroOfertaEcoTec
    @xml text
    as
    DECLARE @hDoc int
    Begin transaction
    	EXEC sp_xml_preparedocument @hDoc OUTPUT, @xml
    	Declare @IdOferta int
    	Insert into OFERTAS (USUARIOID,LICITACIONID,MREQUERIMIENTOID,PROVEEDORID,GPO,GEN,ESP,DIF,VAR,PRECIO_OFERTADO,CANT_MAX,DESCUENTO)	
    	SELECT * FROM OPENXML(@hDoc, N'/ROOT/OfertaEcoTec') with (USUARIOID INT,LICITACIONID int,REQID int, PROVEEDORID int,GPO char(3),GEN char(3),ESP char(4),DIF char(2),[VAR] char(2),PRECIOOFER float,CANTMAXOFER int,DESCUENTOOFER float)
    	
    	Select @IdOferta =@@identity
    	If @@error <>0 
    		Rollback Tran
    	Else
    		Insert into MARC_OFERT (OFERTAID,MARCA,OFICIO_EXIME,TRAMITE_INCLUSION,ORIGEN,FABRICANTE,RFC_FABRICANTE)		
    		SELECT @IdOferta,* FROM OPENXML(@hDoc, N'/ROOT/OfertaEcoTec/MARCASOFER') with (MARCA VARCHAR(200),OFICIO VARCHAR(200), INCLUSION VARCHAR(200), ORIGEN VARCHAR(200),FABRICANTE VARCHAR(200),RFCFAB VARCHAR(30))
    		EXEC sp_xml_removedocument @hDoc
    	If @@error <>0 
    		Begin 
    			Rollback Tran
    			Return 
    		End 
    	Else
    Commit Tran

    pero al momento de hacer la conexion y mandar el parametro al SP me manda el siguiente error:

    No hay ninguna asignación de tipo de objecto system.IO.StringWriter a un tipo nativo de un proveedor administrado conocido.- System.Data

    Alguien podría ayudarme con este error, de antemano muchas gracias.


    Horacio Xochitemol Bautista

    jueves, 10 de septiembre de 2015 18:57
  • Hola, buenas.

    No puedes pasar el StringWriter str como parámetro al procedimiento almacenado. En lugar de pasar la variable str tal cuál, debes pasar el contenido, invocando al método ToString. El método ToString del StringWriter recupera el contenido del mismo en formato cadena.

    https://msdn.microsoft.com/en-us/library/system.io.stringwriter.tostring(v=vs.110).aspx

    Prueba a hacer el siguiente cambio:

    ...
    cmd.Parameters.AddWithValue("@xml", str.ToString());
    ...
    Un saludo.


    When an answer is helpful, please vote as helpful, propose as answer and/or mark as answer

    • Editado ohawari viernes, 11 de septiembre de 2015 8:10
    viernes, 11 de septiembre de 2015 8:10
  • Gracias amigo ya lo pude pasarlo al SP; ahora bien en mi tabla tengo columnas que debe ser unicas; el SP no inserta la informacion en la tabla 1(columnas con campos unicos)  pero si en la tabla 2, es decir no captura el error podrian echarme una mano por favor el SP es el siguiente.

    USE [MCCUR]
    GO
    /****** Object:  StoredProcedure [dbo].[PGUARDA_OFERTA_ECO_MAESTRO_DETALLE]    Script Date: 10/09/2015 06:18:04 p.m. ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER Procedure [dbo].[PGUARDA_OFERTA_ECO_MAESTRO_DETALLE]
    @xml text
    as
    DECLARE @hDoc int
    
    Begin TRANSACTION
    
    DECLARE @Error int
    	EXEC sp_xml_preparedocument @hDoc OUTPUT, @xml
    	Declare @IdOferta int
    	Insert into OFERTAS (USUARIOID,LICITACIONID,MREQUERIMIENTOID,PROVEEDORID,GPO,GEN,ESP,DIF,VAR,PRECIO_OFERTADO,CANT_MAX,DESCUENTO,PRECIO_NETO)	
    	SELECT * FROM OPENXML(@hDoc, N'/ROOT/OfertaEcoTec') with (USUARIOID INT,LICITACIONID int,REQID int, PROVEEDORID int,GPO char(3),GEN char(3),ESP char(4),DIF char(2),[VAR] char(2),PRECIOOFER float,CANTMAXOFER int,DESCUENTOOFER float,PRECIONETO float)
    	Select @IdOferta =@@identity
    	--almacendo el error  por si no se ejecuta la instruccion correctamente
    	SET @Error=@@ERROR
    	--si la variable de error es diferente de cero ejecuto el codigo para cancelar la transaccion
    	if (@Error<>0) GOTO TratarError
    	   --si el primer inset se realiza con exito pasamos al segundo insert de marcas
    		Insert into MARC_OFERT (OFERTAID,MARCA,OFICIO_EXIME,TRAMITE_INCLUSION,ORIGEN,FABRICANTE,RFC_FABRICANTE)		
    		SELECT @IdOferta,* FROM OPENXML(@hDoc, N'/ROOT/OfertaEcoTec/MARCASOFER') with (MARCA VARCHAR(200),OFICIO VARCHAR(200), INCLUSION VARCHAR(200), ORIGEN VARCHAR(200),FABRICANTE VARCHAR(200),RFCFAB VARCHAR(30))
    		EXEC sp_xml_removedocument @hDoc
    	    
    		SET @Error=@@ERROR
        if (@Error<>0)  GOTO TratarError
    		
    		COMMIT TRANSACTION	 
    		
    TratarError: 
     if @@ERROR <>0 
      BEGIN
    	PRINT 'Ocurrio un error durante la transaccion'
    	ROLLBACK TRANSACTION
      END
    


    Horacio Xochitemol Bautista

    • Marcado como respuesta Xochitemol martes, 15 de septiembre de 2015 0:36
    viernes, 11 de septiembre de 2015 14:39