I have a vb .net ArrayList that I would like to store in one field on my Ms SQL 2008 database. Is it possible to put it in and get it back out as an ArrayList?
I'm guessing i need to break down the Array some how and store it as a string, then rebuild it when reading back as i dont see any datatypes for sql that are for arrays. Which is a bummer for me!
Can anyone suggest the best way to do this?
Many thanks.
edit - The ArrayList stores a set of quote ID's. There is no limit to how big it is so it could hold 1 or 1001 different ID's
This is probably part of a one-to-many relationship. Say for example your ArrayList is storing strings, then create a separate table, where one of its fields in this string value. You can send the ArrayList as a param to your DALC class and loop through it there, adding one record at a time to the DB by calling a stored proceedure, etc.
You can use a serializer such as
var serializer = new XmlSerializer(typeof(ArrayList));
var buffer = new StringBuilder();
using(var tw = new XmlTextWriter(new StringWriter(buffer)){
serializer.serialize(tw, myArrayList);
}
var xml = buffer.ToString();
BUT There are a few warnings:
If you have a collection, this is often a sign you should make a many-to-one table but I will assume you know what you are doing and dont need that table
When instantiating XmlSerializer, watch out for memory leaks. It may not apply in your case because you are using a built in type but this is something to be aware of: http://blogs.msdn.com/b/tess/archive/2010/05/05/net-memory-leak-xslcompiledtransform-and-leaked-dynamic-assemblies.aspx
Dim no As Integer() = {11, 22, 33, 44}
Dim MS As New System.IO.MemoryStream
Dim bin As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
bin.Serialize(MS, no)
Dim bytes(MS.Length - 1) As Byte
MS.Position = 0
MS.Read(bytes, 0, bytes.Length)
....
...
cmd.ComandText="insert into TableName values (#data)"
cmd.Parameters.Add("#data", SqlDbType.Image, bytes.Length).Value = bytes
Source: http://www.daniweb.com/software-development/vbnet/threads/253410/save-array-to-database
Related
I am very new to programming in ActionScript3 and using SQLite. Currently I try to make an AIR application where it will handle from small to large dataset from excel, import into and calculate in AIR using ActionScript3 and stored the calculated data in SQLite.
Right now I have 2 question regarding using array to transfer data into SQLite
1. Is it possible to INSERT data or UPDATE data in SQLite without using looping?
In my AIR application, I have an object called DataInput in which have 62 variables/properties which will contain 62 different values from 62 columns in excel. I do know that if you create new instance of DataInput and push into array e.g arDataInput in loop, you can access each of the data in the array using arDataInput[i].variablename where i is the index of the array and variablename is the variables/properties of the object.
Obviously, right now I do actually using for loop to access the value of each cell in excel then calculate in AIR application before transfer the calculated data into SQLite, row by row within sql transaction.
Is there actually a way to transfer data in array into SQLite (either INSERT new row or UPDATE existing row) without using loop like INSERT INTO tblDataInputUW VALUES arDataInput given that each column name in SQLite table is the same as variables/properties of object within the array eg. SQLite table, tblDataInput have column name namePlat and array have variables/properties of arDataInput.namePlat?
2. Is it possible to split the data array i got from SQLite into multiple array without looping?
Right now, I use the following code to extract data from SQLite and stored as an array;
txtSQL = new String();
arData = new Array();
txtSQL = "SELECT namePlat, platLat, platLong FROM tblDataInput";
arData = getSQLData(txtSQL);
function getSQLData(text: String): Array
{
sqlCon.begin();
sqlStat = new SQLStatement();
sqlStat.sqlConnection = sqlCon;
sqlStat.text = text;
sqlStat.execute();
sqlCon.commit();
var result: SQLResult = new SQLResult();
var arData: Array = new Array();
result = sqlStat.getResult();
if (result != null)
{
arData = result.data;
}
return arData;
}
If my assumption are correct, I can access each of the value in arData by using arData[i].variablename where i is the index of the array and variablename is the table name within the SQLite table tblDataInput.
If there are way to split the data in arData into 3 different array e.g arNamePlat without using looping like arNamePlat = arData.variablename because I have many different chart to draw in my AIR application and each chart will have its own array to get value from.
Right now, I actually using different sql statement for different chart like;
txtSQL = new String();
arData = new Array();
txtSQL = "SELECT namePlat FROM tblDataInput";
arData = getSQLData(txtSQL);
dgNamePlat.dataProvider = new DataProvider(arData);
txtSQL = new String();
arData = new Array();
txtSQL = "SELECT platLat, platLong FROM tblDataInput";
arData = getSQLData(txtSQL);
dgPlatLatLong.dataProvider = new DataProvider(arData);
I use the same arData and txtSQL for each chart as I dont store the value anymore after the chart been drawn.
There are actually no restriction for me to just use for loop, I asking this question as I don't see any topic regarding on this question and as a self-learning programmer, I like to explore different way of coding and way to incorporate that knowledge into my projects.
The best way to send and receive data and do database stuff is through form submissions. AIR can POST regular form submissions like html pages but can also load a response. Regular serverside software like php handles the form submission, does whatever with the database, and returns data or simple success message.
The best way to handle data is to use XML (look into RESTful architecture for reasons why). PHP creates XML for the app. The xml gets loaded and should go into arrays of objects.
Here are some good links to get going on submitting data with forms and reading XML:
republic of code tutorials:
http://www.republicofcode.com/tutorials/flash/as3contactform/2.php
http://www.republicofcode.com/tutorials/flash/as3xml/
https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequest.html
https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequestMethod.html
I have changed all my code from the raw ADO.NET SQLCommand to Entity Framework in order to have easier accessibility of changing my code in the future. However, I have realized there are many drawbacks in Entity Framework it is not as simple as injecting raw SQL commands into the database. Moreover, I have used Reverse Engineering to generate the Models & Mapping for MS Sql Server.
Currently, I am trying to do the following but none of the columns are getting updated.
string sql = #"UPDATE [ProductDB] SET CreatedProduct_Time=getdate(), CreatedProduct_Date=getdate()" + " WHERE [Material_No] = #Material_No";
db.Database.ExecuteSqlCommand(sql, new SqlParameter("#Material_No", materialnotxt));
The columns are not getting updated.
I am having a doubt whether Entity Framework will help me maintain my code for future use and is it worth the headache using it instead of the old raw SQL code? So far there are many constraints and it requires a higher learning curve.
Some confusing parts I have find online what is the difference between the context.Database.ExecuteSqlCommand and this MSDN http://msdn.microsoft.com/en-us/library/bb738684.aspx the code looks entirely different then my approach.
EDIT
I have used a different approach to insert the Date and Time while inserting all the info from the textbox.
using (var db = new ROGContext())
{
ProductDB product = new ProductDB
{
Material_No = long.Parse(MaterialNo_txtbox.Text),
Product_Line = ProductLineDropDownList1.SelectedItem.Text,
Product_Description = Description_txtbox.Text,
Size = Size_txtbox.Text,
UOM = UOM_txtbox.Text,
SupplierID = long.Parse(SupplierCountryListBox.SelectedItem.Value),
CreatedProduct_Date = DateTime.Parse(System.DateTime.Now.ToShortDateString()), //in the SQL database I have set the datatype as date to get yyyy/mm/dd
CreatedProduct_Time = DateTime.Now.TimeOfDay //in the SQL database I have set the datatype as time(0) to get hh:mm:ss
};
long queryselect = (from materialno in db.ProductDBs
where materialno.Material_No == product.Material_No
select materialno.Material_No).SingleOrDefault();
if (queryselect != long.Parse(materialnotxt))
{
Label1.Text = "Product successfully added in database";
Label1.Visible = true;
db.ProductDBs.Add(product);
db.SaveChanges();
}
You can use Context.ExecuteStoreCommand for Insert, Update and Delete.
See in Page 64 of Entity Framework 4.0 Recipes: A Problem-Solution Approach
Answer your edited part:
ExecuteStoreQuery for Select
ExecuteStoreCommand for Insert, Update and Delete
Entity Framework v4 – Tips and Tricks
this is a method i was reading about #MSDN ,
my question is if for an example i would like to use it on a stored procedure
with the fact that the query of that stored procedure is already specifying columns to select from the table like following :
SELECT Columnsome, columnother, , , , ...FROM thisSQLdbTable
though i would like to implement the approach of that specific method , it seems very advanced from a little research i have made on
"the best way" available to extract data from SQL Server into Asp.net DataTable.
public static DataTable GetCustomerData(string dataSetName,
string connectionString)
{
DataTable table = new DataTable(dataSetName);
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT CustomerID, CompanyName, ContactName FROM dbo.Customers", connection);
DataTableMapping mapping = adapter.TableMappings.Add("Table", "Customers");
mapping.ColumnMappings.Add("CompanyName", "Name");
mapping.ColumnMappings.Add("ContactName", "Contact");
connection.Open();
adapter.FillSchema(table, SchemaType.Mapped);
adapter.Fill(table);
return table;
}
}
or is it not the method to use if i am querying via SP that specifies the selected column
i could actually drop that stored procedure if it is not requiered to select /specify columns
the stored procedure is doing a specific calculation and updates the table with results of calculation then i am switching it's "MODE" to select results from the table that was updated.
what i did is recyceling (; giving it a parameter (bit type)
stored procedure then asks for the value of supplied bool / bit Parameter,
if its is status true it updates (doing its original task it was made for)
if its false its doing a select oporation so i am using it as i would with 2 separated commands
but now that i have search for a better way to extract data from db into a Data table
i give up on the two way SP and i will make a selection via the exaple above if they're not intended to be used thogether as with my current SP that does preselection when servs the GetCustomersData() above.
So the question is do i need to let the function to make the selection or can i serve it with my sp ready made selection to implemet it with GetCustomersData() in the way that it will only do rest of task and only mapp the columns that was preselected
Still a bit confused on your actual requirement but here goes:
I See you are using a direct query in your C# code, 'best way' would be to make a SP out of it then say:
SqlCommand command = conn.CreateCommand();
SqlDataAdapter sqlAdapter = new SqlDataAdapter(command);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "sp_GetCustomerData";
Then after you have added parameters if needed do:
conn.Open();
sqlAdapter.Fill(dtResult);
conn.Close();
Where dtResult is Datatable.
So you do not need to do any mapping in this case, and since you are using a SP from the Database it will work faster than your direct query and you can change the query logic any time without the need of re deploying your code.
Stored procedures are perfectly valid in this use case. however, if you want more of a properly mapped table, you have several options, some of which go beyond the use of DataTables.
You can use strongly typed DataSets or perhaps use an ORM (object relational mapper).
ref: Typed Datasets: http://msdn.microsoft.com/en-us/library/esbykkzb(v=vs.71).aspx
ref: What is an ORM : http://en.wikipedia.org/wiki/Object-relational_mapping
EXAMPLES OF ORM'S
ref: Entity Framework : http://msdn.microsoft.com/en-us/data/ef.aspx
ref: NHibernate: http://nhforge.org/
I have created an ArrayList with items in my Order.aspx.vb. I pass these on to my bllOrder, which passes it on to my dalOrder.
Order.aspx.vb
Dim item As RepeaterItem
For Each item In rptProductList.Items
objOrder.OrderCustID = Session("CustID")
objOrder.OrderProdID = DirectCast(item.FindControl("ddlProducts"), DropDownList).SelectedValue
bllOrder.InsertOrder(objOrder)
Next item
dalOrder
Function InsertOrder(ByVal objOrder As Order) As Boolean
Dim Result as New Boolean
myconn.open()
Dim SQL As String = "INSERT INTO order(OrderCustID, OrderProdID) VALUES (?,?)"
Dim cmd As New OdbcCommand(SQL, myconn)
cmd.Parameters.AddWithValue("OrderCustID", objOrder.OrderCustID)
cmd.Parameters.AddWithValue("OrderProdID", objorder.OrderProdID)
result = cmd.ExecuteNonQuery()
myconn.close()
Return Result
End Function
This is good for one item, but how would I do it for my ArrayList?
All help is much appreciated!
instead of passing single Order item, pass a List of Orders and them loop it though inside your method. make it like that Public Function InsertOrder(objOrder As List(Of Order)) As Boolean and then use objOrder as a list of Orders to loop it through.
put the following code inside a foreach loop following code and pass the current item values;
cmd.Parameters.AddWithValue("OrderCustID", objOrder.OrderCustID)
cmd.Parameters.AddWithValue("OrderProdID", objorder.OrderProdID)
result = cmd.ExecuteNonQuery()
Convert the array of items into an xml string and you can do a bulk insert in the stored procedure using openxml. http://msdn.microsoft.com/en-us/library/ms191268.aspx also refer an older post for sql server 2005 http://weblogs.asp.net/jgalloway/archive/2007/02/16/passing-lists-to-sql-server-2005-with-xml-parameters.aspx
** edited to account for extra info **
You could adapt the existing "for each" logic in your codebehind to build an arraylist or List<> of products - this array/list should be a property of your Order object. Pass the Order object to the DAL via your BAL as currently.
Then iterate through the products in the Order object in the DAL code(InsertOrder) and either
insert each row individually in a
loop
or dynamically build an insert statement for the Order
.
You should wrap it in a transaction to ensure the order is rolled back competely if one row fails to insert.
For orders with large amout of products i'd go for #Aravind's answer.
I’d use SqlClient.SqlBulkCopy. This is effectively a .Net version of Bulk Insert, to use it you need to either have your objects you want to insert in a either a DataTable or create a class to read your data that implements IDDataReader. If your inserting 1,000’s of rows then you should see a dramatic performace increase and much tidier code.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx
Please go through the following link
How to insert a c# datetime var into SQL Server
I will suggest you to use the comma seperated values . Do not send the array list in your DAL Layer instead a function should return a formatted comma seperated value from the Presentation Layer and send this value to DAL and finally seperate the values in your stored procedure.
Alternative
You can format your values in an XML and send it to Stored Procedure.
In order to perform it your parameter should be of varchar type.
It might sound kiddish or silly but i wanna know that in codes like..
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
rdr.Read();
Response.Write(rdr[1]. ToString());
how do we use the SqlDataReader object as an array (rdr[1]) without declaration?
What I want to know is, what is happening in the following line?
Response.Write(rdr[1].ToString());
Since rdr is an object, how art we able to use square brackets with that?
You are looking for Indexers.
Please refer to this link.
Indexers are a syntactic convenience
that enable you to create a class,
struct, or interface that client
applications can access just as an
array
ref: http://msdn.microsoft.com/en-us/library/2549tw02.aspx
you can do something like this.
Object[] values = new Object[reader.FieldCount];
int fieldCount = reader.GetValues(values);
Console.WriteLine("reader.GetValues retrieved {0} columns.",
fieldCount);
for (int i = 0; i < fieldCount; i++)
Console.WriteLine(values[i]);
Console.WriteLine();
No, since SqlDataReader is a forward-only read-only stream of rows from a SQL Server database, the stream of rows will be looped through whether explicitly in your code or hidden in a framework implementation (such as DataTable's Load method). So you cannot directly convert it to array type. You need to convert it to list.
It sounds like using a generic list and then returning the list as an array would be a good option. For example,
List list = new List();
while (rdr.Read())
{
list.Add(rdr.GetInt32(0));
}
return list.ToArray();