how to query strongly type datatable - asp.net

I have a news portal.
For this portal I have a database with a "News" table and with the following columns
(NewsID, CategoryID, NewsTitle, NewsText, DateAdded, ImagePath, TotalRead, NewsType, isActive)
I use dataset files (.xsd) and for this one, I have a query that returns the last 3 days' news into a custom class that I coded, named HHNews.
HHNews Class has a function that returns a strongly-typed datatable that includes the results of the query I mention above.
The home page has different sections for news.. these are;
- Headlines (5 items)
- Sub-headings (4 items)
- Last 5 news items for each of the news categories...( categories are like; sports, local news, economics,
For the home page, I retrieve the datatable returned from the class. Now I want to query this datatable and build the sections I mention above.. e.g.
if my datatable is called "dt", then is there a way to sql-like query this dt such as "select TOP(5) NewsID, NewsTitle, NewsText from dt where NewsType = 0" -- 0 representing the headline ?

Absolutely. You can use LINQ as Dave Cluderay mentioned. To retrieve your headlines, for example, you could run:
var myDataTable = dt.AsEnumerable();
var headlines = myDataTable.Where(t => t.NewsID == 0).Take(5);

You can use LINQ to DataSet if you're in .NET 3.5.

If you aren't in .NET 3.5, you can create a DataView based on the DataTable object and then set the RowFilter property on the DataView. For example:
DataView myDV = new DataView(dt);
myDV.RowFilter = "NewsType = 0";
You can then catch only the first 5 rows in your DataView.

You can use the default view to filter the datatable like so:
dt.DefaultView.RowFilter = "NewsType = 0";
Not sure how you would get the top 5!?

If you're not in 3.5 you could use a simple for loop to get the top 5 rows after sorting the table.

There is a Select method on the Datatable, dont think there is a way to limit the amount returned. I like the LINQ way, but just an alternative....but the limit might count this out.
dt.Select("NewsType = 0");

Related

Linq to Entities Many to Many Query WPF DataGrid

I have a Many to Many relationship in SQL Server 2008:
Student table (StudentID as PK, StudentName)
Course table (CourseID as PK, CourseName)
StudentCourse (Pure Junction Table) (StudentID, CourseID both in a composite PK).
In Visual Studio 2010:
Entity model is setup properly.
I have a DataGrid bound to:
<CollectionViewSource x:Key="CourseViewSource" d:DesignSource="{d:DesignInstance my:Course, CreateList=True}" />"
This allows me to set the dataGrid columnsproperty to BOTH tables: CourseName AND to Students.StudentName.
I need to show ALL Students in ALL Courses they are in, on the same dataGrid.
My query is:
` var context = new context();
var List = from y in context.Courses
from z in y.Students
select y;
dataGrid1.ItemsSource = List;`
This query returns the first student in table Student in all courses and it gets repeated, but I can't show the other students that are taking the same courses AND other courses.
Question:
How can I change the query using linq to entities. I have tried many things for many days.
Thanks in advance.
Try Include instead, like this:
var List = (from y in context.Courses.Include("Students") select y).ToList();

Displaying customers from SQL Server database using datalist control in asp.net

I have got a list of 1000 customers which I am displaying through a datalist control in asp.net. The list shows one customer per page.
The query I am using to bound the data list is :
static public DataTable GetAllCustomers()
{
string sql = "Select * from [Customers]";
SqlDataAdapter da = new SqlDataAdapter(sql, ConnectionString);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
What I want to do is once the customer is viewed it should go back to the bottom of the list, so that once the user logged in second time , he dont have to start from the beginning viewing the same customer, the viewed customers should go to bottom of the 1000 customer list, for instance if once customer 1 is viewed, the next time the customer 1 should become 1000 customer and the customer 2 should become customer 1, hope it make sense.
Any suggestion or assistance will be appreciated on how to achieve this scenario & what changes do i have to make in the db and query to achieve this.
When the customer is viewed capture the current datetime and use sorting, orderby datetime ascending order
Create a new column in the same table. Whenever you view the customer update the customer with the current date and time for .this newly created column
ALTER TABLE YourTableName
ADD NewColumnName DATETIME DEFAULT getdate()
The newly created column should have all values initially updated by current date and time. This means the default value of this column will be GetDate()
When you bring all record from database sort it by column . Thus you will have unviewed customers at the top every time...
static public DataTable GetAllCustomers()
{
string sql = "Select * from [Customers]";
using (SqlDataAdapter da = new SqlDataAdapter(sql, ConnectionString))
{
using (DataTable dt = new DataTable())
{
da.Fill(dt);
return dt;
}
}
}
Hope this will help you...
First you need somewhere to remember what is the last CustomterID that you show, and the Max rows of your customers.
Let say that the LastCustomerID -> CuLast and Max rows -> CuMax, then the SQL can be like.
WITH CustomersNewOrder as (
select *, CustomerID-CuLast as OrderMe from Customers where CustomerID > CuLast
union
select *, CustomerID+CuMax as OrderMe from Customers where CustomerID <= CuLast
) select * from CustomersNewOrder order by OrderMe
also When the CuLast > CuMax then make the CuLast = 0
What I do here is that the number is the last is starting from 0, and the one that you have all ready show starting after the maximum of the list.
This way you do not need to make update to database, and only one number needs to remember, the last one you show.
Because you say that you won to be the same for all users, and I suppose that you have one pool only, then a static value anywhere on global space can do the job that keeping the last one show.

Using arraylist to insert items into DB

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.

Databinding with LINQ

I'm databinding a radiobuttonlist with a LINQ query like so:
var query = from m in Db.Udt_Menu
orderby m.Name
select m;
this.radMenuSelection.DataValueField = "menuID";
this.radMenuSelection.DataTextField = "name";
this.radMenuSelection.DataSource = query;
this.radMenuSelection.DataBind();
However, when i want to update the record I need to set the selectedindex of the radiobutton to a value from the database. There is a table called udt_PageMenuSelection which has a column called menuID which is a foreign key to udt_Menu.menuID.
When i want to update an existing record, how do i set the selectedindex of the radiolist to the value equal to udt_PageMenuSelection.menuID ?
Do I need to do an additional query?
Thanks
higgsy
I think I understand the structure, and yes it seems the best way to do things; the udt_Menu entity would have a relationship to udt_PageMenuSelection as a one to many relationship, and you could use LoadWith<> to load those, but that is overkill since I think you are talking loading one record. It would be best to just query it separately.
HTH.

DataBind to specific records

I have a DataGridView binded to this table:
[Users]
ID Name
-- ----
11 Qwe
22 Asd
Grid is direclty binded to typed dataset table.
I have a second table like this:
[Records]
ID UserID Data
-- ------ ----
67 11 ....
68 11 ....
Records.UserID is connected to Users with a foreign key.
What I want to do is: when the user doubleclicks User #11 I open a new grid, binded to [Records] table but only binded to rows where UserID = 11. Doubleclick, getting ID, new grid etc. those are OK. I wouldn't had any problems if I was doing this connected with sprocs but I want it to be binded and I simply have no idea how to do this.
Can you please give me any ideas?
If you are using DataSets/DataTables, then you can do something like this to filter your rows for the second grid:
string filter = String.Format("UserID = {0}", selectedUserId);
grdRecords.DataSource = ds.Tables["Records"].Select(filter);
I believe you can edit the records in the array that is returned, but you won't be able to add/remove new items to this collection. You would have to add them to the regular table, then refilter the grid.
Of course, there's all kinds of other ways to do this as well. If you are using objects that derive from IBindingListView, such as instances of the DataView class, you should have access to the Filter property. Then you can just do this:
string filter = String.Format("UserID = {0}", selectedUserId);
DataView myView;
grdRecords.DataSource = myView;
myView.Filter = filter;
And your view will stay filtered to match whatever data you place into it.
Hopefully, this post is clear enough for you to be able to work out the details... I'm a little scatterbrained today. :)
In the end I had to this:
Create a DB class, with a public property (MyDataSetProperty) that returns the typedDataset
Create a custom Fill function in DataSet that accepts an Id parameter.
Use this function to fill the table in the private typedDataset
this.myTableAdapter.FillCustom(this.myTypedDataset.MyTable, this.Id);
Bind bindingSource to this public property:
this.bindingSource.DataSource = this.db.MyDataSetProperty;

Resources