How to Insert DataTable with values into Database in Linq to sql - asp.net

I want to save all record exist in a DataTable into my database. I am using Linq-to-SQL in C#.
I am using this code:
DataTable dt = null;
dt = getTable(fl.ToString()); //getting DataTable
using (DataClassesDataContext dc = new DataClassesDataContext())
{
foreach (var mt in dc.Mapping.GetTables())
{
if (dt.TableName == mt.TableName)
{
//How to insert this table values in DB??
}
}
}
Please suggest me better way to do that.
Thanks in advance.

Well, the whole point of using something like Linq-to-SQL is the fact that it gives you proper .NET objects to work with, instead of the clumsy, untyped DataTable.
So if you use Linq-to-SQL properly, you should retrieve your data as .NET objects using Linq-to-SQL, then you should modify your .NET objects, and use Linq-to-SQL again to store the data.
Something like this:
// set up your Linq-to-SQL DataContext
using (AdventureWorksDataContext ctx = new AdventureWorksDataContext())
{
// get some data - use the *OBJECTS* returned to you! Not a DataTable!
List<Customer> customers = ctx.Customers.Take(10).ToList();
// modify data
foreach (Customer c in customers)
{
c.ModifiedDate = DateTime.Now;
}
// save the changes
ctx.SubmitChanges();
}
So if you have a DataTable, what I'd suggest is converting those DataRows into some kind of an object type that's stored in your database, and then storing that information into the database using Linq-To-SQL - something like this:
public void SaveData(DataTable table)
{
// set up your Linq-to-SQL DataContext
using (AdventureWorksDataContext ctx = new AdventureWorksDataContext())
{
// iterate over the data rows
foreach (DataRow row in table.Rows)
{
// Convert the DataRow to an object
YourObjectType myData = ConvertDataRowToObject(row);
// add this data to the Linq-to-SQL data context
ctx.YourObjectTypes.InsertOnSubmit(myData);
}
// save the changes
ctx.SubmitChanges();
}
}

Related

Dapper question. Getting values from returned object

Just started learning Dapper. I have an ADO.NET background. Using a demo I downloaded, I can insert/delete data from a webform into a MySql table just fine. This, however, I have searched all morning on.
In retrieving a single row from the db by ID, it doesn't return a LIST<>, it seems to be just an object (using code from the demo I downloaded). The query works, I get the object back. It has the fields: "ProductID, Description and Price".
The only way I could get the values to those three fields was like this:
System.Reflection.PropertyInfo pi = Product.GetType().GetProperty("ProductID");
System.Reflection.PropertyInfo desc = Product.GetType().GetProperty("Description");
System.Reflection.PropertyInfo price = Product.GetType().GetProperty("Price");
int _ProductID = (int)(pi.GetValue(Product, null));
string _Description = (string)(desc.GetValue(Product, null));
decimal _Price = (decimal)(price.GetValue(Product, null));
This works and gets the correct values for the three fields.
I'm used to looping through DataTables, but I just think there is probably a better way to get those values.
Is this the correct way to do this or am I missing something? I did actually read documentation and mess with this all morning before asking, too.
Some of the things I looked at seem to be very complex. I thought Dapper was supposed to simplify things.
OK, Thanks Marc. It was difficult for me to see what was supposed to be in the Dapper class files and what was supposed to be in my code behind. The original demo way of getting a product by ID had the query as .FirstOrDefault();
I changed everything to return a List<> and it all worked. I'm sure my ADO.NET is showing, but this works. In Dapper class files:
public List<Product> ProductAsList(int Id)
{
return this._db.Query<Product>("SELECT * FROM Cart_product WHERE ProductID=#Id", new { Id = Id }).**ToList()**;
}
This is just getting one row that matched the ProductID.
In page codebehind:
protected void CartItemAdd(string ProductId) // passing it the selected ProductID
{
var results = cartservice.ProductAsList(Convert.ToInt32(ProductId));
// returns that one row using Dapper ProductAsList(ProductId)
int _ProductId = 0;
string Description = string.Empty;
decimal Price = 0;
// Loop through the list and get the value of each item:
foreach (Product obj in results)
{
_ProductId = obj.ProductID;
Description = obj.Description;
Price = obj.Price;
}
// Using Dapper to insert the selected product into the shopping cart (table):
String UserName = "jbanks";
cartitem = new CartItem();
cartitem.ProductID = _ProductId;
cartitem.Quantity = 1;
cartitem.Description = Description;
cartitem.Price = Price;
cartitem.Created = DateTime.Now;
cartitem.CreatedBy = UserName;
result = cartservice.AddCartItem(cartitem);
if (result)
{
lblMessage.Text = string.Empty;
lblMessage.Text = "Successfully added a cart item";
}
}
}
It does indeed look up the product from one table and insert a selected item into another table.
Thanks again!
The main Query<T> API returns an IEnumerable<T>, which often will be a List<T>; the AsList<T>() extension method can get it back to a list without a copy, but either way: they are just T, for whatever T you asked for. If you asked for Query<Product>, then: they should be Product instances:
var results = connection.Query<Product>(someSql, someArgs); // perhaps .AsList()
foreach (Product obj in results) { // "var obj" would be fine here too
// now just use obj.ProductID, obj.Description and obj.Price
}
If that didn't work: check that you used the <T> version of Query. There is a non-generic variant too, which returns dynamic. Frankly, you should almost always use the <T> version.
Note: I'm assuming that somewhere you have something like
class Product {
public int ProductID {get;set;}
public string Description {get;set;}
public decimal Price {get;set;}
}

Is it possible to create an ADOX catalog in memory and populate it?

I tried creating one like this:
using (MemoryStream stream = new MemoryStream())
{
Catalog catalog = new Catalog(stream); // do I need to add more after this?
foreach (DataTable dt in ds.Tables)
{
Table adoxTable = new Table();
adoxTable.Name = dt.TableName;
adoxTable.ParentCatalog = catalog; // issue is here
catalog.Tables.Append(table);
}
return stream.ToArray();
}
However when I get to the line adoxTable.ParentCatalog = catalog; I get the exception: The connection cannot be used to perform this operation. It is either closed or invalid in this context.
Do I need to add additional steps after creating the catalog in order to properly utilize it?

"Cannot add an entity that already exists" while deleting and recreating record with LINQ

While trying to delete a record in a database and recreate it afterwards, using LINQ, I get the error: Cannot add an entity that already exists.
Although the record is deleted.
I am initialising my Sales_header object with data I get from a LINQ query in method
SelectOrdersByOrderID(OrderID).
If the OrderID of the Salesheader meets a certain condition, I want to delete the record in the database (Delete(Sales_header SalesHeader)), add additional values to the object and insert a new record in the database (Insert(Sales_header SalesHeader)).
I do not want to update the record, but delete it and recreate it.
Sales_header SalesHeader = new Sales_header();
SalesHeader = SalesHeaderClass.SelectOrdersByOrderID(OrderID) as Sales_header;
if (SalesHeader.OrderID == *certain value*)
{
SalesHeaderClass.Delete(SalesHeader);
SalesHeader.Orderdate = DateTime.Today;
SalesHeader.Ordertime = DateTime.Now;
SalesHeaderClass.Insert(SalesHeader);
}
...
Method in SalesHeaderClass to select the SalesHeader via LINQ
public static object SelectOrdersByOrderID(int OrderID)
{
var Query = (from p in dc.Sales_headers
where p.OrderID.Equals(OrderID)
select p).SingleOrDefault();
return Query;
Method in SalesHeaderClass to insert the SalesHeader via LINQ
public static void Insert(Sales_header SalesHeader)
{
dc.Sales_headers.InsertOnSubmit(SalesHeader);
dc.SubmitChanges();
}
Method in SalesHeaderClass to delete the SalesHeader via LINQ
public static void Delete(Sales_header SalesHeader)
{
var DelOrder = (from p in dc.Sales_headers
where p.OrderID == SalesHeader.OrderID
select p).Single();
dc.Sales_headers.DeleteOnSubmit(DelOrder);
dc.SubmitChanges();
}
What do I have to do to be able to insert the record?
Creating a new object with the same values does not help.
Aside from the question why an update is not suitable.
You need two contexts to first delete the record, and then insert the record. EF keeps all inserts/updates/deletes in memory until you do a SubmitChanges(), so you cannot have two entities with the same ID.
But to execute the whole things as a single transaction, you're going to need a TransactionScope.
using (var scope = new TransactionScope()) {
using (var salesHeader SalesHeader = new Sales_header()) {
// Delete record
...
salesHeader.SubmitChanges();
}
using (var salesHeader SalesHeader = new Sales_header()) {
// Insert record
...
salesHeader.SubmitChanges();
}
// Mark transaction complete
scope.Complete();
}
To fix this issue, use different datacontext for delete and insert operation.

Arraylist and list issue in C#

I have a arraylist of employees from the gridview in my ASP.net Page as shown below:
ArrayList tempempList = new ArrayList();
List<Employee> emps = new List<Employee>();
for (int i = 0; i < gvemp.Rows.Count; i++)
{
if (((CheckBox)gvemp.Rows[i].FindControl("cbAssign")).Checked)
{
tempempList.Add(((Label)gvemp.Rows[i].FindControl("lblempSeqNo")).Text);
}
}
Now I have List and Employee object consists of the following properties
empID, empName,empAge,empSalary
Now for each empID from tempempList I need to populate the List
I am not sure how I can populate emps.
Appreciate your help
The List<T> object is just the strongly-typed version (generic) of ArrayList. ArrayList is preserved for traditional purposes, and List<T> should be utilized when necessary.
You can call the List<T>.Add() method, just like you did for the ArrayList.Add() method. So something like:
emps.Add(yourValue);
That should suffice.

how do i convert IEnumerable<MyClass> to DataTable very fast?

I'm familiar with the reflection method that converts any IEnumerable to DataTable, but it's very very slow!
When i get not huge but big chunk of data i get very slow browser reaction, because it's very complicated data to handle.
I need to boost my prefformance, how do i do it?
PS: Checked LazyLoading DataTable no success there ether, maybe someone will show me how to do it?
Thank you very very much in advance.
See this artice for detailed explanation.
Core code sample
public static DataTable ToDataTable<T>(this IEnumerable<T> collection)
{
DataTable dt = new DataTable();
Type t = typeof(T);
PropertyInfo[] pia = t.GetProperties();
//Create the columns in the DataTable
foreach (PropertyInfo pi in pia)
{
if ((pi.PropertyType.IsGenericType) )
{
Type typeOfColumn = pi.PropertyType.GetGenericArguments()[0];
dt.Columns.Add(pi.Name, typeOfColumn);
}
else
dt.Columns.Add(pi.Name, pi.PropertyType);
}
//Populate the table
foreach (T item in collection)
{
DataRow dr = dt.NewRow();
dr.BeginEdit();
foreach (PropertyInfo pi in pia)
{
dr[pi.Name] = pi.GetValue(item, null);
}
dr.EndEdit();
dt.Rows.Add(dr);
}
return dt;
}
}
Why do you think that data converting slows your app? Did your profile it?

Resources