We need to populate a bunch of controls on a form using Linq-to-SQL to retrieve the data. In order to get the data, we need to join several tables.
We have the following method:
First file:
public IEnumerable<object> getPRs()
{
DataContext db = new DataContext();
var prQuery = (from p in db.Invoice
join prd in db.InvoiceDetails on p.ID equals prd.ID
join pra in Accounting on p.ID equals pra.ID
where 1 == 1
orderby p.DownloadDate descending, p.PRNumber, Convert.ToInt32(p.Item)
select new
{
p.ID,
DownloadDate = Convert.ToString(p.DownloadDate),
p.PRNumber,
p.Item,
p.Material,
p.ClientMaterial,
p.Description,
p.Client,
p.Price,
p.UC,
prd.Supplier,
prd.Duns,
prd.RFQ,
prd.RFQDate,
prd.PO,
prd.PODate,
POValue = prd.Price * prd.Quantity,
pra.SO,
pra.SODate,
pra.SOValue,
pra.GR,
pra.GRDate,
pra.GI,
pra.GIDate,
pra.SInvoice,
pra.SInvoiceDate,
pra.CInvoice,
pra.CInvoiceDate,
p.isActive
}).ToList();
return prQuery;
}
And we are calling the method like this on the second file:
IEnumerable<object> data = FirstFile.GetPRs();
PRNumberTextBox.Text = data.PRNumber;
The last line will give an error because we can't access the PRNumber
member from the data object. In order to fill in all the text boxes, how can we call our function and add the necessary info?
You are returning an anonymous type. I would recommend you create a model class to return your data:
public class PRModel
{
public int ID { get; set; }
public string DownloadDate { get; set; }
//etc... you can fill in the rest yourself
}
Then your query becomes something like this:
var prQuery = (from p in db.Invoice
join prd in db.InvoiceDetails on p.ID equals prd.ID
join pra in Accounting on p.ID equals pra.ID
where 1 == 1
orderby p.DownloadDate descending, p.PRNumber, Convert.ToInt32(p.Item)
select new PRModel //<---This is the change here
{
ID = p.ID,
DownloadDate = Convert.ToString(p.DownloadDate),
PRNumber = p.PRNumber,
//snipp
}
And finally, your return type should now be IEnumerable<PRModel>
. Also, as it's an enumeration (ie you may have 0, 1 or many items) you need to iterate through them:
IEnumerable<PRModel> data = FirstFile.GetPRs();
foreach(var pr in data)
{
PRNumberTextBox.Text = pr.PRNumber;
}
Edit:
In this case, if you only want to return an individual invoice, it's even easier to do. Instead of doing this:
select new PRModel
{
//lots of rows
}
You could simply do this:
select p
Which in turn makes your return type IEnumerable<Invoice>
.
Issue :
PRNumber
is not a member of IEnumerable<object>
. You need to iterate through IEnumerable
to access each element.
Solution:
Second issue is that you're implicitly casting anonymous types from linq query to an object so every element in a list you get from getPRS()
will be an object . You can't access properties without casting to a specific type (as per @DavidG solution - new class/type for every aggregate function) or defining type at a runtime using dynamic
. The easiest fix will be to change return type to IEnumerable<dynamic>
:
public IEnumerable<dynamic> GetList()
{
var list = new List<int> {1, 2, 3, 4};
return (from i in list
select new {
Integer = i,
Str = "Str" + i
}).ToList();
}
and then:
var items = GetList();
Console.WriteLine(items.First().Integer); // prints "1" to console
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.