Store and retrieve data table into Varbinary column - sql-server

For some reason I had to store a DataTable variable in a Varbinary column of a SQL Server table, but I get errors.
This is store code:
// Read DataTable to Byte array
DataTable dtgrd = new DataTable();
DataAccess ds = new DataAccess();
DataSet dst = new DataSet();
dst.Tables.Add(dtgrd);
string xmlString = dst.GetXml();
MemoryStream ms = new MemoryStream();
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlString);
xml.Save(ms);
byte[] xmlBytes = ms.ToArray();
// Store DataTable into database
SqlConnection CN = new SqlConnection(Global.cs);
string str = #"INSERT INTO...... ";
SqlCommand SqlCom = new SqlCommand(str, CN);
SqlCom.Parameters.Add(new SqlParameter("#FKDocInReqID", FKDocInReqID));
SqlCom.Parameters.Add(new SqlParameter("#value", (object)xmlBytes));
SqlCom.Parameters.Add(new SqlParameter("#Data", ReportTitle));
SqlCom.Parameters.Add(new SqlParameter("#DocUploadUser_secuserID", Global.S_UserID));
CN.Open();
decimal id =(decimal) SqlCom.ExecuteScalar();
CN.Close();
The store code has worked correctly and in the database, the columns has the proper bytes.
But the retrieve code does not work:
string s = #"select * from .... where id={0} ";
s = string.Format(s, id);
DataTable dt = new DataTable();
dt = ds.doSelect(s);
using (System.IO.MemoryStream memStream1 = new System.IO.MemoryStream((byte[])dt.Rows[0]["Value"]))
{
dataGridView1.DataSource = FromBytes(memStream1.ToArray());
dataGridView1.Refresh();
dataGridView1.Show();
}
and
static DataTable FromBytes(byte[] arr)
{
using (var ms = new MemoryStream(arr))
{
return (DataTable)new BinaryFormatter().Deserialize(ms);//**ERROR Raised Here**
}
}
static byte[] ToBytes(DataTable table)
{
using (var ms = new MemoryStream())
{
table.RemotingFormat = SerializationFormat.Binary;
new BinaryFormatter().Serialize(ms, table);
return ms.ToArray();
}
}
this error is raised:
error message

The example code on Microsoft's website uses XmlTextReader
static DataTable FromBytes(Stream st)
{
var ds = new DataSet();
using (XmlTextReader xmlReader = new XmlTextReader(st))
{
ds.ReadXml(xmlReader);
}
return ds.Tables[0];
}
I'll leave you to think about the obvious design flaws in storing one table within another.

this is how I figure out this problem maybe help to someone else.
instead of save data into Varbinary field save it to xml in nvarchar(max) and then retrieve it :
//Retrieve Process:
string s = #"select * from .... where id={0} ";
s = string.Format(s, ID);
DataTable dtlist = new DataTable();
DataAccess ds = new DataAccess();
dtlist = ds.doSelect(s);//doselect is function that run select sql command
XmlDocument xml = new XmlDocument();
xml.LoadXml(dtlist.Rows[0]["Data"].ToString());//data is column name that store xml in it
StringReader theReader = new StringReader(xml.InnerXml);
DataSet theDataSet = new DataSet();
theDataSet.ReadXml(theReader);
gridEX1.DataSource = theDataSet.Tables[0];

Related

ds.Tables["TableName"] threw an exception "System.Data.DataTableCollection.this[string].get returned null."

I'm working on a Exporting DataGridView to CSV File and I have this problem:
When i try with table name ( ds.Tables["tableName"] ) it threw an exception "System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.Data.DataTableCollection.this[string].get returned null.
"
but it is working with the index of table: ds.Tables[0].
In my case I have only the names of the table.
I've tried with ds.Tables["dbo.tableName"] also ds.Tables[(row.Cells["table_name"].Value.ToString())]
this is my code:
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
foreach (DataGridViewRow row in TableNamesGrid.Rows)
{
bool isSelected = Convert.ToBoolean(row.Cells["CheckBox"].Value);
if (isSelected)
{
StringBuilder stringBuilder = new StringBuilder();
SqlDataAdapter sqlData = new SqlDataAdapter("SELECT * FROM " + row.Cells[1].Value, sqlConnection);
DataSet ds = new DataSet();
sqlData.Fill(ds);
foreach (DataRow dataRow in ds.Tables[(row.Cells["table_name"].Value.ToString())].Rows)
{
for (int i = 0; i <= ds.Tables[(row.Cells["table_name"].Value.ToString())].Rows.Count; i++)
{
stringBuilder.Append(dataRow[i].ToString() + ",");
}
stringBuilder.Append("\r\n");
}
StreamWriter file = new StreamWriter(#"D:\Projects\AlatiWF\data.csv");
file.WriteLine(stringBuilder.ToString());
file.Close();
}
}
}
}
The SqlDataAdapter is not smart enough to work out that your query is just accessing a single table, so it will always return tables named like this: "Table0", "Table1", "Table2", etc.
Table[0] works because it's accessing the table called "Table0". You can give the tables sensible names after your call to sqlData.Fill(ds) by doing something like:
ds.Tables[0].TableName = "SensibleTableName";
Directly fill the Datatable and without Dataset.
DataTable dt = new DataTable();
sqlData.Fill(dt);
foreach (DataRow dataRow in dt.Rows)
{

How to import data from a .DBF file into SQL Server?

So far I have a successful connection retrieving data from a .dbf file but I can not figure out how to store this data into my database. Currently I have my connection with SQL Server and connection string name is PortageleafPickupEntities1 which holds three columns Address, SeasonType, and NextPickupdate.
Now this .dbf data has all the data for each column just got to tranfer it there.
Here is the code...
public HttpResponseMessage Post([FromBody]LeafPickup pickup )
{
string cadena = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\\Users\\azib\\Desktop\\dfb; Extended Properties = dBASE IV; User ID = Admin; Password =";
string select = "Select * from sp18br ";
DataSet myDataSet = new DataSet();
OleDbConnection con = new OleDbConnection(cadena);
OleDbCommand myAccessCommand = new OleDbCommand(select, con);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter(myAccessCommand);
con.Open();
myDataAdapter.Fill(myDataSet, "sp18br");
con.Close();
DataTableCollection dta = myDataSet.Tables;
foreach (DataTable dt in dta)
{
Console.WriteLine("Found data table {0}", dt.TableName);
}
Console.WriteLine("{0} rows in sp18br table", myDataSet.Tables["sp18br"].Rows.Count);
DataRowCollection dra = myDataSet.Tables["sp18br"].Rows;
foreach (DataRow dr in dra)
{
// Print the CategoryID as a subscript, then the Name:
Console.WriteLine("\n" + " {0} -- {1} -- {2} -- {3} -- {4} ", "\n" + dr[0], dr[1], dr[2], dr[3], dr[4]);
}
using (PortageLeafPickupEntities1 entities = new PortageLeafPickupEntities1())
{
entities.LeafPickups.Add(pickup);
entities.SaveChanges();
var message = Request.CreateResponse(HttpStatusCode.Created, pickup);
message.Headers.Location = new Uri(Request.RequestUri + pickup.ID.ToString());
return message;
}
}

ado.net does not return data in SQL Builtin function

I have following method, but it does not fill datatable.
using (conn = new SqlConnection(Connection1))
{
conn.Open();
string query = "SELECT distinct left(RTRIM(PostalCode), 2),EntityID FROM Gen_Addresses";
dt = new DataTable();
ad = new SqlDataAdapter(query ,conn);
ad.Fill(dt);
checkedListBox1.DisplayMember = dt.Columns["PostalCode"].ColumnName;
checkedListBox1.ValueMember = dt.Columns["EntityID"].ColumnName;
}
using (conn = new SqlConnection(Connection1))
{
conn.Open();
string query = "SELECT distinct left(RTRIM(PostalCode), 2),EntityID FROM Gen_Addresses";
SqlCommand cmd=null;
cmd=new SqlCommand(query ,conn);
dt = new DataTable();
ad = new SqlDataAdapter();
ad.SelectCommand=cmd;
ad.Fill(dt);
checkedListBox1.DisplayMember = dt.Columns["PostalCode"].ColumnName;
checkedListBox1.ValueMember = dt.Columns["EntityID"].ColumnName;
}
try this
You need to specify a column alias in the query in order to reference the expression by name instead of ordinal:
string query = "SELECT distinct left(RTRIM(PostalCode), 2) AS PostalCode,EntityID FROM Gen_Addresses";

Read XML from SQL Server using OleDbDataReader

I'm stuck trying to read XML data from SQL Server using OleDb.
private static void Main(string[] args){
var con = new OleDbConnection("Provider=SQLNCLI11.1;Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Temp");
var cmd = new OleDbCommand(
"SELECT [Id] ,[Description] FROM [Temp].[dbo].[SomeTable] where [Id]= 1 for xml path, root('root')", con);
con.Open();
byte[] result = null;
OleDbDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (reader.Read()){
result = (byte[]) reader[0];
}
MemoryStream stream = new MemoryStream(result);
stream.Position = 0;
XmlDocument doc = new XmlDocument();
doc.Load(stream);
Console.Out.WriteLine(doc.OuterXml);
}
It fails saying that data is malformed. If I convert the byte array to string I see a lot of "strange " characters. What I'm doing wrong?
Since the result is direct XML I believe you are facing issue.You need to get the result in row-set instead of scalar.
Read as String, Use LoadXML instead of stream.
Below is the code I changed.
private static void Main(string[] args)
{
var con = new OleDbConnection("Provider=SQLNCLI11.1;Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Temp");
var cmd = new OleDbCommand(
"Select (SELECT [Id] ,[Description] FROM [Temp].[dbo].[SomeTable] where [Id]= 1 for xml path, root('root')) AS XML", con);
con.Open();
string result = string.Empty;
OleDbDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (reader.Read())
{
result = reader[0].ToString();
}
con.Close();
XmlDocument doc = new XmlDocument();
doc.LoadXml(result);
Console.Out.WriteLine(doc.OuterXml);
}

Fill observableCollection directly from sql server

I would like to know if there is any way to fill ObservableCollection directly from SQL server.
Currently I am loading my data into DataTable (using sqlDataAdapter) and do a conversion to ObservableCollection manually and it very inefficient.
How it can be done?
OK, I have found a way to do this:
It can be done using SqlDataReader.
public ObservableCollection<DataItem> LoadCategoriesData()
{
Command = new SqlCommand(StoredProcedure, Connection);
Command.CommandType = CommandType.StoredProcedure;
ObservableCollection<DataItem> myColl = new ObservableCollection<DataItem>();
Connection.Open();
SqlDataReader reader = Command.ExecuteReader();
while (reader.Read())
{
int mainCatID = reader.GetInt32(0);
string categoryName = reader.GetString(1);
//adding row data to observable
myColl.Add(new DataItem(mainCatID, categoryName));
}
Connection.Close();
return myColl;
}

Resources