views:

46

answers:

1

Hi, [Below is the almost full Code modified. Currently shows illegal character error when being read]. I have a C# ASP.NET application which is currently reading an xml file from the file system and then loading it into a GridView control. In the grid I can Delete rows. There is also an file upload button below the grid which upload PDF files and they show up in the grid. My code is basically a modified version of: http://sureshsharmaaspdotnet.wordpress.com/2008/07/04/editupdatedelete-in-gridview-using-xml-file/

The next stage of my work involves reading the xml data as String from a database field--instead of from the xml file. For that to happen, I think I can start out by just reading from the xml file, making changes in the aspx page, and the writing the 'dataset' into a database field called 'PDF_Storage'. How can I do that. Crucially, I need to be able to convert the dataset into some kind of string format for storage. Here is my code snippet.

My database is Oracle 10 but I can figure out the Update sql syntax.

Thanks!

SAMPLE XML FILE:

<DataSet><PDF><pdf>MyPDF1.pdf</pdf></PDF><PDF><pdf>MyPDF2.pdf</pdf></PDF><PDF><pdf>MyPDF3.pdf</pdf></PDF></DataSet>





  using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Oracle.DataAccess.Client;
using System.Web.Configuration;
using System.IO;
using System.Xml;
using System.Text.RegularExpressions;

public partial class XMLGridTest : System.Web.UI.Page
{
    public static string GetConnString()
    {
        return WebConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            binddata();
        }
    }
    void binddata()
    {
        DataSet ds = new DataSet();
      // ds.ReadXml(Server.MapPath("testxml.xml"));
        String strConnect = GetConnString();
        OracleConnection oracleConn = new OracleConnection();
        oracleConn.ConnectionString = strConnect;
        oracleConn.Open();
        OracleCommand cmd = new OracleCommand();
        cmd.Connection = oracleConn;
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "SELECT PDF_Storage FROM CampusDev.CU_POLY WHERE OBJECTID = " + Request.QueryString["OBJECTID"];
        OracleDataReader reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            if (!reader.IsDBNull(0))
            {


              //## Line Below as the 'illegal characters' problem###
               ds.ReadXml(reader[0].ToString(), XmlReadMode.IgnoreSchema);
                 gv.DataSource = ds;
                gv.DataBind();

            }
            else
            {
                // Response.Write(reader.GetString(1));
                // TextBox1.Text = reader.GetString(1);
            }
        }
       // gv.DataSource = ds;//##Hard coded for XML. Works!
       //  gv.DataBind();

        //Finally, close the connection
        oracleConn.Close();


    }

    protected void Canceldata(object s, GridViewCancelEditEventArgs e)
    {
        gv.EditIndex = -1;
        binddata();
    }

    protected void pageddata(object s, GridViewPageEventArgs e)
    {
        gv.PageIndex = e.NewPageIndex;
        binddata();
    }

    protected void insert(object sender, EventArgs e)
    {
        /////////////////////////////////File Upload Code/////////////////////////////////
        // Initialize variables
        string sSavePath = "ParcelPDF/"; ;
        if (fileupload.PostedFile == null)
        {
            Label1.Text = "Must Upload a PDF file!";
            return;
        }
        HttpPostedFile myFile = fileupload.PostedFile;
        int nFileLen = myFile.ContentLength;

        // Check file extension (must be JPG)
        if (System.IO.Path.GetExtension(myFile.FileName).ToLower() != ".pdf")
        {
            Label1.Text = "The file must have an extension of .pdf";
            return;
        }
        // Read file into a data stream
        byte[] myData = new Byte[nFileLen];
        myFile.InputStream.Read(myData, 0, nFileLen);
        // Make sure a duplicate file doesn’t exist.  If it does, keep on appending an incremental numeric until it is unique
        string sFilename = System.IO.Path.GetFileName(myFile.FileName);
        int file_append = 0;
        while (System.IO.File.Exists(Server.MapPath(sSavePath + sFilename)))
        {
            file_append++;
            sFilename = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) + file_append.ToString() + ".pdf";
        }

        // Save the stream to disk
        System.IO.FileStream newFile = new System.IO.FileStream(Server.MapPath(sSavePath + sFilename), System.IO.FileMode.Create);
        newFile.Write(myData, 0, myData.Length);
        newFile.Close();
        binddata();
        DataSet ds = gv.DataSource as DataSet;
        DataRow dr = ds.Tables[0].NewRow();
        // dr[0] = pdf.Text;
        dr[0] = sFilename.ToString();
        ds.Tables[0].Rows.Add(dr);
        ds.AcceptChanges();
        string blah = "blah";
        Response.Write(ds.Tables.ToString());
        //  ds.WriteXml(Server.MapPath("testxml.xml"));
        String strConnect = GetConnString();
        OracleConnection oracleConn = new OracleConnection();
        oracleConn.ConnectionString = strConnect;
        oracleConn.Open();
        OracleCommand cmd = new OracleCommand();
        cmd.Connection = oracleConn;
        cmd.CommandType = CommandType.Text;
        // cmd.CommandText = "SELECT OBJECTID,COMMENTS FROM CampusDev.CU_POLY WHERE OBJECTID = " + Request.QueryString["OBJECTID"];
        cmd.CommandText = "UPDATE CampusDev.CU_POLY SET PDF_Storage = :PDF_Storage WHERE OBJECTID = " + Request.QueryString["OBJECTID"];
        StringWriter SW = new StringWriter();
        ds.WriteXml(SW);
        cmd.Parameters.Add(":PDF_Storage", SW.ToString());
        cmd.ExecuteNonQuery();
        oracleConn.Close();
        binddata();
    }

    protected void Deletedata(object s, GridViewDeleteEventArgs e)
    {
        binddata();
        DataSet ds = gv.DataSource as DataSet;
        ds.Tables[0].Rows[gv.Rows[e.RowIndex].DataItemIndex].Delete();
        //  ds.WriteXml(Server.MapPath("testxml.xml"));//Disabled now. Do database. Irfan. 07/09/10
        String strConnect = GetConnString();
        OracleConnection oracleConn = new OracleConnection();
        oracleConn.ConnectionString = strConnect;
        oracleConn.Open();
        OracleCommand cmd = new OracleCommand();
        cmd.Connection = oracleConn;
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "UPDATE CampusDev.CU_POLY SET PDF_Storage = :PDF_Storage WHERE OBJECTID = " + Request.QueryString["OBJECTID"];
        StringWriter SW = new StringWriter();

        ds.WriteXml(SW,XmlWriteMode.IgnoreSchema);
        Regex regex = new Regex(@"(\r\n|\r|\n)+");
        string newText = regex.Replace(SW.ToString(), "");
        cmd.Parameters.Add(":PDF_Storage", newText);
        cmd.ExecuteNonQuery();
        oracleConn.Close();
        binddata();
        string blah = "blah";
    }
A: 

Hi,

Here is how I have done this in the past. For the insert you can basically just write the dataset's xml representation out to a string and save it directly to a field in the database. In this case I leveraged Sql Server 2008 and an XML datatype for the database field. I think the datatype in Oracle is XMLTYPE.

Insert:

public static void InsertDataSet(string key, DataSet dataSet)
{
  string xml = string.Empty;

  using (MemoryStream ms = new MemoryStream())
  {
    dataSet.WriteXml(ms, XmlWriteMode.WriteSchema);

    ms.Position = 0;

    using (StreamReader sr = new StreamReader(ms))
    {
      xml = sr.ReadToEnd();
    }

    using (SqlServerConnection c = new SqlServerConnection(connectionString))
    {
      c.command.CommandType = CommandType.StoredProcedure;
      c.command.CommandText = "some stored procedure to do the insert";
      c.command.Parameters.Clear();

      c.command.Parameters.Add(new SqlParameter("@key", key));
      c.command.Parameters.Add(new SqlParameter("@xml", xml));

      c.command.ExecuteNonQuery();
    }
  }
}

Getting the dataset back out of the database is as simple as reading the xml data from the database back into a TextReader and then building a new DataSet.

Get:

public static DataSet GetDataSet(string key)
{
  using (SqlServerConnection c = new SqlServerConnection(connectionString))
  {
    c.command.CommandType = CommandType.StoredProcedure;
    c.command.CommandText = "some stored procedure to get the xml";
    c.command.Parameters.Clear();

    c.command.Parameters.Add(new SqlParameter("@key", key));

    dr = c.command.ExecuteReader();

    if (dr == null)
    {
      return null;
    }

    if (dr.HasRows)
    {
      while (dr.Read())
      {
        if (dr["xml_field"] != DBNull.Value)
        {
          TextReader tr = new StringReader(dr["xml_field"].ToString());

          result = new DataSet();
          result.ReadXml(tr, XmlReadMode.ReadSchema);
        }
      }
    }
  }

  return result;
}

Hope this helps.

Enjoy!

Doug
Hi, Thanks! But my database field 'PDF_Storage' is in Character/string kind of datatype in the database; it should not matter though, right?
meengla
You could save it to a text/string/character field type but xml is going to be more efficient. You can do this in the short term but I would suggest moving the datatype to the native oracle xml type for longterm use.
Doug
I agree, but unfortunately the database is out of my direct reach and it takes jumping through hoops to make changes. I need to get it working via text first. So will your code still work for the datatype of string/character for the 'PDF_Storage' field in the database or do I need to modify it?
meengla
Yes the code should work fine, again, just not very optimized without the xml datatype. Once you have it working you should have enough "proof" to get your dba to change the datatype for you.
Doug
Thanks, Doug! I am working on it. I will let you know. This site is amazing. Quick responses and all free!
meengla
Getting closer. But not sure about adding the command.AddParameter in my case?cmd.CommandText = "UPDATE CampusDev.CU_POLY SET PDF_Storage = :PDF_Storage WHERE OBJECTID = " + Request.QueryString["OBJECTID"];// cmd.Parameters.Add(":PDF_Storage", ds.Tables[0]);//## This would work for string datastring xml = string.Empty; MemoryStream ms = new MemoryStream();ms.Position = 0;ds.WriteXml(ms, XmlWriteMode.WriteSchema);StreamReader sr = new StreamReader(ms);xml = sr.ReadToEnd();c.command.Parameters.Add(new SqlParameter("@key", key));c.command.Parameters.Add(new SqlParameter("@xml", xml));
meengla
Okay! Per http://forums.asp.net/p/1557123/3835825.aspxI have the 'Update' sql working by simply doing:StringWriter SW = new StringWriter(); ds.WriteXml(SW); cmd.Parameters.Add(":PDF_Storage", SW.ToString()); cmd.ExecuteNonQuery();Now on to the Read part of this data...
meengla
Yes you do not need to use Parameters if you do not want to - this code was originally setup to use stored procedures but you could just build the xml yourself.
Doug
I am making progress except I notice that the command ds.WriteXml(SW) creates an XML which has line breaks like /r/n introduced. That is causing problem in reading the XML data from the database. May be there is some 'ignoreWhiteSpace' command?
meengla
where is it causing issues? creating the Textreader?
Doug
I think when the UPDATE is done, as per above code, it introduces '/r/n' and these characters, when Read, are giving an 'illegal character' problem. THE XML Looks like '<DATASET>/r/n<PDF>/r/n<pdf>mypdf.pdf</pdf>/r/nafter the initial insert. So the culprit code must be: StringWriter SW = new StringWriter(); ds.WriteXml(SW); cmd.Parameters.Add(":PDF_Storage", SW.ToString());
meengla
Here is precisely what the database field has after the Insert: reader[0] "<DataSet>\r\n <PDF>\r\n <pdf>MyPDF1.pdf</pdf>\r\n </PDF>\r\n <PDF>\r\n <pdf>MyPDF3.pdf</pdf>\r\n </PDF>\r\n</DataSet>" object {string}as in Visual Studio's Debug panel.
meengla
This is how I am reading the data from the database and I am getting the illegal character error in line 1 below: ds.ReadXml(reader[0].ToString(), XmlReadMode.ReadSchema); gv.DataSource = ds; gv.DataBind();
meengla
Anyone? I mean, I am very close except for the insertion of these \r\n characters!
meengla
I have now removed the \n\r characters from the code which Writes the XML and inserts that into the database: ds.WriteXml(SW,XmlWriteMode.IgnoreSchema); Regex regex = new Regex(@"(\r\n|\r|\n)+"); string newText = regex.Replace(SW.ToString(), ""); cmd.Parameters.Add(":PDF_Storage", newText); but I still get the error of Illegal characters when trying to read the data in: ds.ReadXml(reader[0].ToString(), XmlReadMode.ReadSchema); gv.DataSource = ds; gv.DataBind();
meengla
If you post your code and a sample xml I will see if i can figure out what the issue is.
Doug
Sample XML binds fine to the GridView. It is the data coming from the database which gives the 'illegal characters' problem when being read.Let me post as an 'Answer' below
meengla
Okay, the whole code is posted above as the Edit to the original question.Thanks for your help!
meengla
Also just posted the sample xml file which works fine for both reading into the GridView. I have even managed to remove the characters like '\n' '\r' from the XML data which is being written to the datbase but still the illegal character error.
meengla
May be a solution there:http://objectmix.com/xml-soap/83136-readxml-illegal-characters-path.html
meengla
The issue is that you are trying to initialize the dataset by loading the xml string directly from your database. This will not work as you have experienced. You need to first build a TextReader object and use that to initailze the DataSet.TextReader tr = new StringReader(dr["xml_field"].ToString());result = new DataSet();result.ReadXml(tr, XmlReadMode.ReadSchema);Look at the Get code section from my original post. Also since you are not including a schema with the xml you will need to use XmlReadMode.InferSchema instead of XmlReadMode.ReadSchema.
Doug
Never mind: Got it to work: ds.ReadXml(new StringReader(reader[0].ToString()));per: http://dotnet.itags.org/dotnet-architecture-design/133847/Doug, thanks for all your help!
meengla
Yes you have it! Enjoy!!!
Doug