How to multiply 2 values from different tables in Linq? - c#

I try to multiply 2 values from different table but it's keep error like this:
Here's my code:
//Label12 is in datalist
var Label12 = (Label)(((Button)sender).Parent).FindControl("Label12");
var item2 = from c in db.OrderTemps
join o in db.Products
on c.Prod_ID equals o.Prod_ID
select new
{
o.Prod_ID,
o.Prod_Price, //Type "Decimal"
c.Amount, //Type "Integer"
c.Total, //Type "Decimal
s = o.Prod_Price * c.Amount
};
foreach (var i in item2)
{
Label12.Text = Convert.ToString(i.s); //an error happen here!!
}
Any help appreciated.

There is nothing wrong with you LINQ query. If no records joined, then there will be nothing to enumerate and you will skip foreach body. I think you have Label12 equal to null. Check if it really exist on senders parent.
SIDE NOTE: Why are you trying to assign text in loop? Label will keep only last value assigned.

Check whether your amount value in OrderTemps table is null. or Check whether you really have a controller which has the ID = Label12.
Nothing wrong in your Linq query...

Related

Issues with ListView here in C#

So I'm working on learning LINQ and was assigned to work with two .txt files and to join them.
So far I'm doing well, but I've reached a bit of an impasse with the display. I'm supposed to have the name display once and then the following cases that are closed have only the case information.
The issue I'm having is that the name keeps repeating after the dataset is listed in the ListView. I think there is something wrong with the LINQ statement or the way I'm going through the foreach loop. Here is the code for the main form below:
//Fills the lists by calling the methods from the DB classes
techs = TechnicianDB.GetTechnicians();
incidents = IncidentDB.GetIncidents();
//Creates a variable to use in the LINQ statements
var ClosedCases = from Incident in incidents
join Technician in techs
on Incident.TechID equals Technician.TechID
where Incident.DateClosed!= null
orderby Technician.Name, Incident.DateOpened descending
select new { Technician.Name, Incident.ProductCode, Incident.DateOpened, Incident.DateClosed, Incident.Title };
//variables to hold the technician name, and the integer to increment the listview
string techName = "";
int i = 0;
//foreach loop to pull the fields out of the lists and to display them in the required areas in the listview box
foreach (var Incident in ClosedCases)
{
foreach (var Technician in ClosedCases)
{
if (Technician.Name != techName)
{
lvClosedCases.Items.Add(Technician.Name);
techName = Technician.Name;
}
else
{
lvClosedCases.Items.Add("");
}
}
lvClosedCases.Items[i].SubItems.Add(Incident.ProductCode);
lvClosedCases.Items[i].SubItems.Add(Incident.DateOpened.ToString());
lvClosedCases.Items[i].SubItems.Add(Incident.DateClosed.ToString());
lvClosedCases.Items[i].SubItems.Add(Incident.Title);
i++;
}
And here is the result I get: Result
As can be seen by the bar on the right hand side, the list continues on for several more columns.
What am I missing here?
Thank you.
EDIT: Per request, here is what the results are supposed to look like:
The example I was given
Why you are iterating closed cases twice?
foreach (var Incident in ClosedCases)
{
foreach (var Technician in ClosedCases)
{
}
}

Dynamic linq backslash in where clause

I use System.Linq.Dynamic to query entities with dynamic 'where' expressions. I'm querying object that has property "newValue" of string type. Exemplary value would be : "{\"ProcessId\":764, \"ProcessLength\":1000}".
I can't use == because I want to find all hits where the property contains "ProcessId:764", regardless on the rest of the string. The thing is, that stored string contains escape sign "\" and double quotes and I can't figure out what it should like exactly..
dbContext.Processes.Where("#newValue.Contains(\"ProcessId\":764\")") brings error, however dbContext.Processes.Where("#newValue.Contains(\":764\")") works correctly. I guess it must be something with backslashes or double quotes in my query but can't figure it out on my own..
There are two things to note here:
If you know at compile time the column that should be queried (i.e., newValue), just use standard Linq: var list = items.Where(i => i.NewValue.Contains("904")).ToList().
If you do want to use dyanmic Linq, What you'd usually want is to apply Where on some column, e.g. Where("SomeColumn.Contains("something")"), or Where("SomeColumn.Contains(#0)", new string[] {"something"}).
So, in your case, this should work: items.Where("newValue.Contains(\"904\")").
Doing Where("#newValue.Contains("something")") doesn't really make sense, since #newValue would be parsed as a string literal. See also this comment on a similiar question.
Here' a quick example:
public static void Main(string[] args)
{
var items = new []
{
new { Id = "1", Title = "ProcessId: 123"},
new { Id = "4", Title = "ProcessId: 456"},
new { Id = "7", Title = "ProcessId: 789"},
}.ToList();
// returns null, because the string "Title" doesn't contain the string "7"
var res1 = items.Where("#0.Contains(\"7\")", new string[] {"Title"}).FirstOrDefault();
// works - returns the 3rd element of the array
var res2a = items.Where("Title.Contains(#0)", new string[] {"ProcessId: 789"}).FirstOrDefault();
var res2b = items.Where("Title.Contains(\"ProcessId: 789\")").FirstOrDefault();
}
#HeyJude Thanks for the effort, but I still can't get it to work. It has somehow gone wronger and now I can't even fetch correct rows giving only ProcessId number..
Let me give you more detailed description of my setup. In the database there's a table with column "NewValue", I use this column to store json string of current (for the time of creating row in the table) representation of some object e.g. object Process. So the column stores for example string of {"ProcessId":904,"ProcessLength":1000}. To fetch this data from db I create collection of table's records: var items = (from l in db.JDE_Logs
join u in db.JDE_Users on l.UserId equals u.UserId
join t in db.JDE_Tenants on l.TenantId equals t.TenantId
where l.TenantId == tenants.FirstOrDefault().TenantId && l.Timestamp >= dFrom && l.Timestamp <= dTo
orderby l.Timestamp descending
select new //ExtLog
{
LogId = l.LogId,
TimeStamp = l.Timestamp,
TenantId = t.TenantId,
TenantName = t.TenantName,
UserId = l.UserId,
UserName = u.Name + " " + u.Surname,
Description = l.Description,
OldValue = l.OldValue,
NewValue = l.NewValue
});. Then I query it to find matching rows for given ProcessId number e.g. query = "#NewValue.Contains(\"904,)\")";
items = items.Where(query);
This should fetch back all records where NewValue column contains the query string, but this doesn't work. It compiles and 'works' but no data are fetched or fetched are only those records where 904 appears later in the string. Sounds stupid but this is what it is.
What should the query string look like to fetch all records containing "ProcessId":904?

Linq Query on DataTable and Update Records

I have a datatable in memory and I need to select some records from it, walk through the records making changes to fields and they same the changes back to the datatable. I can do this with filters, views, and sql but I'm trying to do it in Linq.
var results = (from rows in dtTheRows.AsEnumerable()
select new
{
rows.Job,
}).Distinct();
foreach (var row in results)
{
firstRow = true;
thisOnHand = 0;
var here = from thisRow in dtTheRows.AsEnumerable()
orderby thisRow.PromisedDate
select new
{
thisRow.OnHandQuantity,
thisRow.Balance,
thisRow.RemainingQuantity
};
foreach(var theRow in here)
{
// business logic here ...
theRow.OnHandQuantity = 5;
} // foreach ...
The first linq query and foreach are gain the list of subsets of data to be considered. I include it here in case it is relevant. My problem is at this line:
heRow.OnHandQuantity = 5;
My error is:
"Error 19 Property or indexer 'AnonymousType#1.OnHandQuantity' cannot be assigned to -- it is read only"
What am I missing here? Can I update this query back into the original datatable?
var here = from thisRow in dtTheRows.AsEnumerable()
orderby thisRow.PromisedDate
select new
{
thisRow.OnHandQuantity,
thisRow.Balance,
thisRow.RemainingQuantity
};
Instead of passing three variables in select, pass thisRow itself. That may solve error on statement - theRow.OnHandQuantity = 5;
The error is self descriptive, you can't update/modify an anonymous type. You have to return the original entity you want to modify from your query.
select thisRow;
instead of
select new
{
thisRow.OnHandQuantity,
thisRow.Balance,
thisRow.RemainingQuantity
};

Search values only from first element in linq c#.net

I have the problem in where condition please check this
<Uni_Details Uni_ID="U001" User_Mode="New">
<Uni_Name>
<Full_Name>Asian</Full_Name>
<Short_Name />
</Uni_Name>
<Asc_Uni>
<Asc_Details Asc_Name="Stafford">
<Asc_Add>fsfadfsdfsdfsdf</Asc_Add>
<Asc_Tel>+44 34234234234</Asc_Tel>
<Asc_Country>United Kingdom</Asc_Country>
<Asc_Web>www.ac.lk</Asc_Web>
</Asc_Details>
</Asc_Uni>
<Branch>
<Branch_Details Branch_Name="Head Office">
<Branch_Add>dasdasdadsd</Branch_Add>
<Branch_City>Colombo</Branch_City>
<Branch_Country>Sri Lanka</Branch_Country>
<Branch_Tel>+94 342432423</Branch_Tel>
</Branch_Details>
<Branch_Details Branch_Name="Access Tower">
<Branch_Add>dfgdfgdfgdf</Branch_Add>
<Branch_City>Colombo</Branch_City>
<Branch_Country>Sri Lanka</Branch_Country>
<Branch_Tel>+94 342432453</Branch_Tel>
</Branch_Details>
</Branch>
<Uni_EMail>info#apiit.lk</Uni_EMail>
<Uni_Web>www.apiit.lk</Uni_Web>
<Course_Data>
<Course_Details Course_ID="U001C001">
<Course_Name>Computer Course</Course_Name>
<Course_Qual>Pass O/L</Course_Qual>
<Course_Dur>3 Months</Course_Dur>
<Course_Content>
<Course_Conent_List>C#.net</Course_Conent_List>
<Course_Conent_List>VB.Net</Course_Conent_List>
<Course_Conent_List>Design Practices</Course_Conent_List>
</Course_Content>
<Course_Fee>
<Fee_Amount Amount_Currency="SL Rs.">5000.00</Fee_Amount>
<Fee_Comment>Onwards</Fee_Comment>
</Course_Fee>
<Course_Desc>Learn Basic Programming practices</Course_Desc>
<Course_Next>Next October</Course_Next>
<Category_List>
<Cat_ID>2</Cat_ID>
<Cat_ID>1</Cat_ID>
</Category_List>
</Course_Details>
</Course_Data>
</Uni_Details>
<Uni_Details Uni_ID="U002" User_Mode="New">
<Uni_Name>
<Full_Name>American College</Full_Name>
<Short_Name>AC</Short_Name>
</Uni_Name>
<Asc_Uni>
<Asc_Details Asc_Name="American College USA">
<Asc_Add>fasdfsdfsdfsdsdfs</Asc_Add>
<Asc_Tel>+94 112 230623</Asc_Tel>
<Asc_Country>United States</Asc_Country>
<Asc_Web>www.ac.lk</Asc_Web>
</Asc_Details>
</Asc_Uni>
<Branch>
<Branch_Details Branch_Name="Head Office">
<Branch_Add>FFSDFASDFSDF</Branch_Add>
<Branch_City>Colombo</Branch_City>
<Branch_Country>Sri Lanka</Branch_Country>
<Branch_Tel>+94 112 230623</Branch_Tel>
</Branch_Details>
</Branch>
<Uni_EMail>info#ac.lk</Uni_EMail>
<Uni_Web>www.ac.lk</Uni_Web>
<Course_Data>
<Course_Details Course_ID="U002C0001">
<Course_Name>Computer Course</Course_Name>
<Course_Qual>O/L Pass</Course_Qual>
<Course_Dur>3 Months</Course_Dur>
<Course_Content>
<Course_Conent_List>C#.net</Course_Conent_List>
<Course_Conent_List>VB.Net</Course_Conent_List>
<Course_Conent_List>Design Practices</Course_Conent_List>
</Course_Content>
<Course_Fee>
<Fee_Amount Amount_Currency="SL Rs.">5000</Fee_Amount>
<Fee_Comment></Fee_Comment>
</Course_Fee>
<Course_Desc>Basics</Course_Desc>
<Course_Next>Next October</Course_Next>
<Category_List>
<Cat_ID>1</Cat_ID>
</Category_List>
</Course_Details>
<Course_Details Course_ID="U002C0002">
<Course_Name>Accounting Course</Course_Name>
<Course_Qual>O/L Pass</Course_Qual>
<Course_Dur>6 Months</Course_Dur>
<Course_Content>
<Course_Conent_List>Accounts Basics</Course_Conent_List>
<Course_Conent_List>Business Studies</Course_Conent_List>
<Course_Conent_List>Acc Pack</Course_Conent_List>
</Course_Content>
<Course_Fee>
<Fee_Amount Amount_Currency="SL Rs.">10000</Fee_Amount>
<Fee_Comment></Fee_Comment>
</Course_Fee>
<Course_Desc>Basic Accounting</Course_Desc>
<Course_Next>Next January</Course_Next>
<Category_List>
<Cat_ID>3</Cat_ID>
<Cat_ID>2</Cat_ID>
</Category_List>
</Course_Details>
</Course_Data>
</Uni_Details>
this is my XML file I need to retrieve all data which cat_id is 1
var data = (from cats in data_file.Elements("Uni_Data").Elements("Uni_Details")
where cats.Element("Course_Data").Element("Course_Details").Element("Category_List").Element("Cat_ID").Value == cat_id.ToString()
select new
{
uni_name = cats.Element("Uni_Name").Element("Full_Name").Value.ToString(),
uni_short = cats.Element("Uni_Name").Element("Short_Name").Value.ToString(),
price = cats.Element("Course_Data").Element("Course_Details").Element("Course_Fee").Element("Fee_Amount").Value.ToString()
});
however this works if I have cat_id 1 as my first element if its in second place it won't listed so plz help me with this
The problem is with the way the end of your where clause is setup: Element("Cat_ID").Value == cat_id.ToString().
Specifically, the Element("Cat_ID") part will check the first child "Cat_ID" element. So if Cat_ID 1 is the second item, it won't be found. Instead, you need to check all child elements for a match.
var data = (from cats in data_file.Elements("Uni_Data").Elements("Uni_Details")
let catId = cats.Element("Course_Data").Element("Course_Details").Element("Category_List").Elements("Cat_ID").FirstOrDefault(c => c.Value == cat_id.ToString())
where catId != null
select new
{
uni_name = cats.Element("Uni_Name").Element("Full_Name").Value.ToString(),
uni_short = cats.Element("Uni_Name").Element("Short_Name").Value.ToString(),
price = cats.Element("Course_Data").Element("Course_Details").Element("Course_Fee").Element("Fee_Amount").Value.ToString()
});
The query uses a let clause to store the result of the FirstOrDefault call, which uses the predicate to match the criteria. Next, if it isn't null then the rest of the query works as before. If it's null it means no match was found.
That said, your query has a lot of repeated elements. It also uses .Value.ToString() in a few places, which is redundant since the Value property already returns a string. I would clean up the query as follows:
var data = from cats in data_file.Elements("Uni_Data").Elements("Uni_Details")
let uniName = cats.Element("Uni_Name")
let details = cats.Element("Course_Data").Element("Course_Details")
let catId = details.Element("Category_List").Elements("Cat_ID").FirstOrDefault(c => c.Value == cat_id.ToString())
where catId != null
select new
{
uni_name = uniName.Element("Full_Name").Value,
uni_short = uniName.Element("Short_Name").Value,
price = details.Element("Course_Fee").Element("Fee_Amount").Value
};

Convert DataTable to LINQ: Unable to query multiple fields

Importing a spreadsheet I have filled a DataTable object with that data and returns expected results.
Attempting to put this into a format I can easily query to search for problem records I have done the following
public void Something(DataTable dt)
{
var data = from row in dt.AsEnumerable()
select row["Order"].ToString();
}
Works as expected giving me a list of orders. However I cannot add other fields to this EnumerableRowCollection. Attempting to add other fields as follows gives me an error
public void Something(DataTable dt)
{
// row["Version"] throws an error on me
var data = from row in dt.AsEnumerable()
select row["Order"].ToString(), row["Version"].ToString();
}
Error: "A local variable named 'row' cannot be declared in this scope because it would give a different meaning to 'row' which is already used in a 'child' scope to donate something else"
I'm thinking I need to alias the column name but I'm having no luck. What am I missing here?
It sounds like you're writing a bad select statement. Try the following:
public void Something(DataTable dt)
{
var data = from row in dt.AsEnumerable()
select new {
Order = row["Order"].ToString(),
Something = row["Something"].ToString(),
Customer = row["Customer"].ToString(),
Address = row["Address"].ToString()
};
}
That will create a new collection of Anonymously Typed objects that you can iterate over and use as needed. Keep in mind, though, that you want be able to return data from the function. If you need that functionality, you need to create a concrete type to use (in place of anonymous types).
I think you should use select new like this query for example:
var q = from o in db.Orders
where o.Products.ProductName.StartsWith("Asset") &&
o.PaymentApproved == true
select new { name = o.Contacts.FirstName + " " +
o.Contacts.LastName,
product = o.Products.ProductName,
version = o.Products.Version +
(o.Products.SubVersion * 0.1)
};
You probably want the following.
var data = from row
in dt.AsEnumerable()
select new { Order = row["Order"].ToString(), Version = row["Version"].ToString() };

Categories

Resources