I know there are quite a few post on this subject but none of them seem to work for me.
I am trying to convert a linq query into an object that is acceptable for my telerik gridview.
What I have:
var allProjectItems = from x in db.DateItems.AsEnumerable()
where
x.Date.ProjectId == projectId
select new
{
ItemDate = (DateTime?)x.Date.ItemDate,
LastName =
((from Users in db.Users
where
Users.UserId == x.Date.AddedByUserId
select new
{
Users.Lastname
}).FirstOrDefault().Lastname),
DateItemId = x.DateItemId,
DateItem1 = x.DateItem1,
DateValue = x.DateValue,
DateId = x.DateId,
DateType = x.DateType
};
I've tried adding .AsEnumerable() onto each table in query but I still am not able to use the query for the gridview or to convert into a datatable with CopyToDataTable method.
Ive also tried to specify requested attributes like x.Field("ProjectId") but Field is not an option.
Can anyone help?
Thanks
Selecting off an anonymous type is going to frustrate you down the road when you actually want to know what object is selected in your gridview.
Just select your DataItem and bind it to your gridview, and set up your Binding on the gridview to show columns for the properties you want to display in the gridview.
//Obviously this is simplified and doesn't include your users stuff, but I think you get the idea.
var allProjectItems = (from x in db.DateItems
where
x.Date.ProjectId == projectId
select x).ToList();
You will have to set up your bindings on your gridview to show the data you want. As for the user business, I'd set up a partial class on the DataItem that will use navigational properties to get the user and return the values you want.
Related
I have a table "Cards" in a database with tables "Cards" and "Customers". Cards contains CustomerID, Number and Ammount. After that, I used ADO.NET to make use of DataGrid, TextBox, etc.
I dropped a DataGrid and a TextBox as a Search Criteria. When a button is pressed, the DataGrid is loaded with the LINQ:
string searchString = this.CustomerIDTextBox.Text();
using (var ctx = new bdCustomerEntities()){
var result = from t in ctx.Cards
join t_customer in ctx.Customer on t.CustomerID equals t_customer.id
where t.CustomerID == searchString
select new
{
number = t.number,
ammount = t.ammount,
CustomerID = t.Customer.id
};
/*Fill datagrid*/
this.CardsDataGrid.ItemsSource = result.ToList();
}
The problem comes when I made a MouseDoubleClick event in the CardsDataGrid to select the row and fill two TextBoxes, one with the Ammount data and the other one with Number.
I tried this code but it fails to show the data in the TextBoxes:
Cards selected = this.cardsDataGrid.SelectedItem as Cards;
this.numberTextBox.Text = selected.Number.ToString();
this.ammountTextBox.Text = seleccionado.Ammount.ToString();
I made a MessageBox.Show after the Cards selected = ... line to see the content on the SelectedItem, and it shows something like this:
{number = 13, ammount = 3500 , CustomerID = 1456 }
My problem is that, I can't "extract" the SelectedItem because of the format created - maybe by the LINQ? - and put that in the TextBoxes.
Something I noticed, when I made this change to the above code:
Cards selected = (Cards) this.cardsDataGrid.SelectedItem ;
It shows:
System.InvalidCastException:Unable to cast object of type
'[System.Int32,System.Int32,System.String]' to type
'bdCustomer.Cards'.
Your LINK is returning an anonymous type not the Cards type, and there is no cast available between the anonymous type and the Cards type, which is what the error is telling you.
Change your LINQ to this:
var result = from t in ctx.Cards
join t_customer in ctx.Customer on t.CustomerID equals t_customer.id
where t.CustomerID == searchString
select t;
In your query result, you return an anonymous type not Cards type and this is the reason you receive InvalidCastException.
You can return the Cards type from your DBSet:
from t in ctx.Cards
join t_customer in ctx.Customer on t.CustomerID equals t_customer.id
where t.CustomerID == searchString
select t;
I have a datagridview that's getting its data from Access via OleDbDataReader.
The problem is as follows
Reading data into Data table then setting datasource = dt => works
dt.Load(dr);
taking the dt and applying Linq to it => empty GridView
GVMultiple.DataSource = (from myRow in dt.AsEnumerable()
where myRow.Field<string>("State") == "Succeeded"
select myRow)
making the Linq.ToList() => shows columns with names "RowError","RowState","Table" and "hasErrors" which aren't my columns
GVMultiple.DataSource = (from myRow in dt.AsEnumerable()
where myRow.Field<string>("State") == "Succeeded"
select myRow).ToList()
Reading data into Object of a custom List then setting datasource = List => empty GridView
while (dr.Read())
{
UserList.Add(new UserInfo()
{
ID = (int)dr["ID"],
UserName = (string)dr["User Name"]
});
}
GVMultiple.DataSource = UserList
Can someone tell me what is going on?
In order to make DataBinding work you've to use Properties. Fields doesn't support DataBinding.
Modify your class as below to make it work.
class UserInfo
{
public int ID {get;set;} //convert fields to property
public string UserName{get;set;}
}
GVMultiple.DataSource = (from myRow in dt.AsEnumerable()
where myRow.Field("State") == "Succeeded"
select myRow)
making the Linq.ToList() => shows columns with names "RowError","RowState","Table" and "hasErrors" which aren't my columns
RowError","RowState","Table" and "hasErrors" are properties of the DataRow - which is what is in the list you created.
Take a look into the .CopyToDataTable() extension method.
http://msdn.microsoft.com/en-us/library/bb396189.aspx
GVMultiple.DataSource = (from myRow in dt.AsEnumerable()
where myRow.Field<string>("State") == "Succeeded"
select myRow).CopyToDataTable();
The reason for that is that the data grid view is not able to recognize the collection of new data as accepted format for display.
When using Linq queries to filter the data and re display it in data grid view you must always return the query result to any data source as data view.
DataView constructs an index, which significantly increases the
performance of operations that can use the index, such as filtering
and sorting. The index for a DataView is built both when the DataView
is created and when any of the sorting or filtering information is
modified. Creating a DataView and then setting the sorting or
filtering information later causes the index to be built at least
twice: once when the DataView is created, and again when any of the
sort or filter properties are modified.
For example:
DataTable dt = empData.loadEmployee();
BindingSource bs = new BindingSource();
bs.DataSource = dt.AsEnumerable()
.Where(c => c.Field<string>("First Name").ToLower()
.Contains(txtSearch.Text.ToLower())).AsDataView();
dgvEmpManag.DataSource = bs;
In the example I am looking for employee with first name like the search term in the text box txtSearch when found the data grid view will display filtered results of my search AsDataView().
I have two DataTables , Items and its Groups. I have a linq query to get item Name and its Group Name by joining the 2 tables.
EnumerableRowCollection<DataRow> dvquery = (from item in Items.AsEnumerable()
join grp in groups.AsEnumerable()
on item.Field<byte>("Group_ID") equals grp.Field<byte>("ID")
into item_grp_join
from itemgrp in item_grp_join
select new
{
ItemName = (string)led.Field<string>("Name"),
GName = (string)itemgrp.Field<string>("Name"),
});
DataView dv = dvquery.AsDataView();
However I am getting compile time error as
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Data.EnumerableRowCollection'. An explicity conversion exists (are you missing a cast?)
How to solve this error? I can easily convert the query result into a list but I need to have a dataview only , so as I can give it as datasource to grid.
Any help appreciated.
Thanks
The problem is that your query returns an IEnumerable<T> of an anonymous type and you can't simply cast that to a EnumerableRowCollection<DataRow>
I'm now sure which type of Grid you are using (e.g. from winforms? WPF? ASP? ASP MVC? etc), however I would expect that you should actually be able to pass it the IEnumerable output of the linq query if you wanted to - e.g.:
var query = (from item in Items.AsEnumerable()
join grp in groups.AsEnumerable()
on item.Field<byte>("Group_ID") equals grp.Field<byte>("ID")
into item_grp_join
from itemgrp in item_grp_join
select new
{
ItemName = (string)led.Field<string>("Name"),
GName = (string)itemgrp.Field<string>("Name"),
});
grid.DataSource = query; // or possible query.ToList() as you suggest in the question!
If you really need to use a DataView type object, then there are blog posts about how to create these, try:
http://www.c-sharpcorner.com/UploadFile/VIMAL.LAKHERA/LINQResultsetToDatatable06242008042629AM/LINQResultsetToDatatable.aspx
http://www.chinhdo.com/20090402/convert-list-to-datatable/
http://wpfguy.blogspot.com/2009/07/how-to-convert-ienumerable-to.html
Note that if you are expecting to use the grid for two-way binding (e.g. for writing changes back to the database), then this is unlikely to "just work" - as your IEnumerable projection isn't tied back to the datasource.
You are returning an list of anonymous objects. It is better to create a DataTable from your query result.
var query = (from item in Items.AsEnumerable() .......
DataTable view = new DataTable();
view.Columns.Add("GroupName");
view.Columns.Add("ItemName");
foreach (var t in dvquery)
{
view.Rows.Add(t.GName, t.ItemName);
}
DataView dv = view.DefaultView;
I'm using LINQ on a Telerik OpenAccess generated data model, to setup a search query and get the results. This all works very well and the code looks very nice.
But now i need to add one more thing, and i'm not sure how to.
The products i'm selecting should have a different price for each customer. The price depends on some other values in 2 other SQL tables. Right now i have the price calculation in a SQL scalar function, but i'm not sure on how to use that in combination with my LINQ.
My goal is to retrieve all data in one database roundtrip, and to be able to sort on this calculated price column as well.
Right now i have something like:
var products = (from p in Products select p);
if(searchOption)
products = products.Where(product => product.Name.Contains(searchOption));
products = products.OrderByDescending(product => product.Name);
products = products.Skip(pageNr * pageSize).Take(pageSize);
I can, of course, use all properties of my Product class, but i want to be able to use a new virtual/calculated property, let say: Product.CalculatedPrice as well.
I have a feeling it should look a bit like this.
(from p in Products
select new {
productId = p.ProductId,
name = p.Name,
calculatedPrice = CalculatedValueFromStoredProcedure/OrScalarFunction(p.ProductId, loggedInCustomerId)
});
Best Regards, Tys
.Select() allows you to create a dynamic type, in which you can extend the product with the calculated price
products.Select(i => new { Product = i, CalculatedPrice = 100})
or in your initial line:
var products = (from p in Products select new { Product = p, CalculatedPrice = 100 });
After doing some more research i've found out that what i want to do is NOT possible in combination with the Telerik OpenAccess ORM! So i've created a workaround that pre-calculates the values i need, put them in a table and join my selection with the contents of that table.
For now, that's the best possible solution i've found.
I have three tables I'm getting info from: User, Field, FieldUserInput. I already know the userId which is what I use to find out what fields the user has input. Then I want to get the value of those fields that the user has input in FieldUserInput.
I first wrote this query in plain old sql but I want to use LINQ as much as possible since that's why I use Entity Framework.
SELECT fielduserinput.field_idField, fielduserinput.userInput, fielduserinput.time
FROM fielduserinput
WHERE fielduserinput.userId = #userId
Any suggestions as to how I would write this in LINQ?
Considering you have a datasource filled with data.
var matchingRows = from rows in fielduserinput.AsEnumarable()
where string.compare(rows["userId"].ToString(),userID)==0
select rows;
var result = from row in fielduserinput
where row.userId = "???"
select new { row.field_idField, row.userInput, ...};
var response = fielduserinput
.Where(x=>x.userid == #userid)
.Select(x=>new { field_idfieldid = x.field_idfieldid, etc })
.ToList()