perform inequality comparisons to alphanumeric data in linq - c#

Need help with linq query. I have a column which contains alphanumeric data in it and I want to extract numbers and perform mathematical comparisons. For example >,< etc.
So the data would be like: JS20, MRR12, DEEN2 etc.
I tried converting it to Int but it fails
var TheData = (from p in db.data.Where(l => Convert.ToInt16(l.TextAndNumber) <= 10)
group p by p.Names into g
select g.Key).ToList();
return Json(new { data = TheData });

Try something like this:
(from row in db.data
let digits = new String(row.TextAndNumber.Where(Char.IsDigit).ToArray())
let number = Int64.Parse(digits)
where number < 10
select row.Names
).Distinct();

You need to extract the numbers from the string before applying your conversion.
List<string> data = new List<string> { "JS20", "MRR112", "DEEN2" };
var TheData = data.Where(d => Convert.ToInt32(new string(d.Where(char.IsNumber).ToArray())) <= 10);
This returns DEEN2.

Related

SQL to LINQ expres

I'm trying to convert a SQL expression to Linq but I can't make it work, does anyone help?
SELECT
COUNT(descricaoFamiliaNovo) as quantidades
FROM VeiculoComSeminovo
group by descricaoFamiliaNovo
I try this:
ViewBag.familiasCount = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo).Count();
I need to know how many times each value repeats, but this way it shows me how many distinct values ​​there are in the column.
You can try:
var list = from a in db.VeiculoComSeminovo
group a by a.descricaoFamiliaNovo into g
select new ViewBag{
familiasCount=g.Count()
};
or
var list = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo)
.Select (g => new ViewBag
{
familiasCount=g.Count()
});
If you need column value:
new ViewBag{
FieldName=g.Key,
familiasCount=g.Count()
};
You don't need the GROUP BY unless there are fields other than the one in COUNT. Try
SELECT
COUNT(descricaoFamiliaNovo) as quantidades
FROM VeiculoComSeminovo
UPDATE, from your comment:
SELECT
COUNT(descricaoFamiliaNovo) as quantidades,
descricaoFamiliaNovo
FROM VeiculoComSeminovo
GROUP BY descricaoFamiliaNovo
That's it as SQL. In LINQ it is something like:
var reponse = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo)
.Select ( n => new
{Name = n.key,
Count = n.Count()
}
)
Not tested.
Ty all for the help.
I solved the problem using this lines:
// get the objects on db
var list = db.VeiculoComSeminovo.ToList();
// lists to recive data
List<int> totaisFamilia = new List<int>();
List<int> totaisFamiliaComSN = new List<int>();
// loop to cycle through objects and add the values ​​I need to their lists
foreach (var item in ViewBag.familias)
{
totaisFamilia.Add(list.Count(a => a.descricaoFamiliaNovo == item && a.valorSeminovo == null));
totaisFamiliaComSN.Add(list.Count(a => a.descricaoFamiliaNovo == item && a.valorSeminovo != null));
}
The query was a little slow than I expected, but I got the data

Split string and use in Select calculation

I'm trying to split a string field and use the values in a calculation in a Select new so I can display the info in a report. The calculation is for the cubic meters of a package. The following code is what I'm using now but when I try to multiply the values from the split string I get an error:
Could not translate expression 'Parse(grp.Key.Length)' into SQL and could not treat it as a local expression
var res = (from packs in data
where packs.DispatchDate != null || (packs.DispatchDate >= DateTime.Parse(_dateFrom).Date &&
packs.DispatchDate <= DateTime.Parse(_dateTo).Date)
orderby packs.Production.DimensionMetric
group packs by
new
{
packs.DispatchDate,
packs.ProductType.TypeDetails,
packs.PackNo,
packs.Thickness,
Width = packs.Production.DimensionMetric.Substring(0,packs.Production.DimensionMetric.IndexOf('x')),
Length = packs.Production.DimensionMetric.Substring(packs.Production.DimensionMetric.IndexOf('x')+1),
packs.Sheets,
}
into grp
select new
{
grp.Key.DispatchDate,
grp.Key.TypeDetails,
grp.Key.PackNo,
grp.Key.Thickness,
grp.Key.Width,
grp.Key.Length,
grp.Key.Sheets,
CBM = ((int.Parse(grp.Key.Length)) * (int.Parse(grp.Key.Length))).ToString(),
}).ToList();
If I just assign or concat the values from Length and width to CBM there is no error, its only when I perform a math calculation on the 2 values. Can someone explain what needs to be done to make this work or do I have to come at it from a different angle?
var res = (from packs in data
where packs.DispatchDate != null || (packs.DispatchDate >= DateTime.Parse(_dateFrom).Date &&
packs.DispatchDate <= DateTime.Parse(_dateTo).Date)
orderby packs.Production.DimensionMetric
group packs by
new
{
packs.DispatchDate,
packs.ProductType.TypeDetails,
packs.PackNo,
packs.Thickness,
Width = packs.Production.DimensionMetric.Substring(0,packs.Production.DimensionMetric.IndexOf('x')),
Length = packs.Production.DimensionMetric.Substring(packs.Production.DimensionMetric.IndexOf('x')+1),
packs.Sheets,
}
into grp
select grp)
.AsEnumerable()
.Select(x=>new {
x.Key.DispatchDate,
x.Key.TypeDetails,
x.Key.PackNo,
x.Key.Thickness,
x.Key.Width,
x.Key.Length,
x.Key.Sheets,
CBM = ((int.Parse(x.Key.Length)) * (int.Parse(x.Key.Length))).ToString(),
})
.ToList();

LINQ query with a where condition containing

I am just learning LINQ and I have come across and issue Im not sure how to do in LINQ.
string numbers = "1,3,4,5";
string[] outletsInaStringArray = outlets.Split(',');
List<string> numbersAsAList = outletsInaStringArray.ToList();
I have a field in my database which holds a number. I only want to select the lines WHERE the number in the database is IN the line list of numbers "1,3,4,5" (these numbers are just examples).
Thanks in advance
I have looked at Tim and James answers and also looked at the line that James has sent. Im still a bit confused.....Sorry. Below is my actual code. It compiles but does not work
string outlets = "1,3,4,5"
string[] outletsNeeded = outlets.Split(',');
List<string> outletsNeededList = outletsNeeded.ToList();
DashboardEntities1 db = new DashboardEntities1();
var deptSalesQuery = (
from d in db.DashboardFigures
where (d.TypeOfinformation == "DEPTSALES") && (outletsNeeded.ToString().Contains(d.OutletNo.ToString()))
select new DeptSales
{
Dn = (int)d.Number,
Dnm = "Mens",
On = d.OutletNo,
Qs = (double)d.Value_4,
Se = (double)d.Value_2,
Si = (double)d.Value_3
}
);
In the DASHBAORDFIGURES table in SQL I have 2 records where the outlets number = 1, and therefore should have come up with two records.
Sorry if this is a simple thing, its just new to me and its frustrating.
You can use Contains as tagged:
var query = db.Table
.Where(x => outletsInaStringArray.Contains(x.Number) && x.information == "SALES");
that was method syntax, if you prefer query syntax:
var query = from figure in db.Figures
where outletsInaStringArray.Contains(figure.number)
&& figure.information == "SALES"
select figure;
But the column number is int, the List<string> stores strings, maybe your LINQ provider does not support .Contains(figure.ToString()). Then convert the strings to int first:
List<int> outletsNeededList = outletsNeeded.Select(int.Parse).ToList();
The answer that Tim provided is one method. Linq and lambda are interchangeable. Have a look at the following posting as well. Link
var result = from x in db.Table.ToList()
where outletsInaStringArray.Contains(x.Number)
select x;
Also have a look the following as it offers a very similar solution to the one you are looking for:
Link
As per i understand, you want to fetch data in similar way as IN (SQL) clause does it.
SELECT <Field_List>
FROM Table
WHERE IntegerField IN (1,2,4,5)
But i'm wondering why do you want to do it that way, when you can join data and get only matches. The worse is that you're trying to mix different data type and pass comma delimited text as a set of integers (i may be wrong):
SELECT <Field_List>
FROM Table
WHERE IntegerField IN ("1,2,4,5")
Above query won't execute, because the set of integers is "packed" into comma delimited string. To be able to execute that query, a conversion between data types must be done. Numbers in a string have to be converted to a set of integers (using user define split function or Common Table Expression):
;WITH CTE AS
(
--here convertion occurs
)
SELECT t2.<Field_List>
FROM CTE As t1 INNER JOIN TableName AS t2 ON t1.MyNumber = t2.IntegerField
Linq + any programming language is more flexible. You can build a list of integers (List) to build query.
See simple example:
void Main()
{
List<MyData> data = new List<MyData>{
new MyData(1,10),
new MyData(2, 11),
new MyData(5, 12),
new MyData(8, 13),
new MyData(12, 14)
};
//you're using comma delimited string
//string searchedNumbers = "1,3,4,5";
//var qry = from n in data
// join s in searchedNumbers.Split(',').Select(x=>int.Parse(x)) on n.ID equals s
// select n;
//qry.Dump();
List<int> searchedNumbers = new List<int>{1,2,4,5};
var qry = from n in data
join s in searchedNumbers on n.ID equals s
select n;
qry.Dump();
}
// Define other methods and classes here
class MyData
{
private int id = 0;
private int weight = 0;
public MyData(int _id, int _weight)
{
id = _id;
weight = _weight;
}
public int ID
{
get{return id;}
set {id = value;}
}
public int Weight
{
get{return weight;}
set {weight = value;}
}
}
Result:
ID Weight
1 10
5 12
Cheers
Maciej
Thank you all iv now got it to work using all your suggestions
the final code that works is as follows
DeptSales myDeptSales = new DeptSales(); // Single department
List<DeptSales> myDeptSalesList = new List<DeptSales>(); // List of Departments
DashboardEntities1 db = new DashboardEntities1();
var deptSalesQuery = from d in db.DashboardFigures
join s in outlets.Split(',').Select(x => int.Parse(x)) on d.OutletNo equals s
where (d.TypeOfinformation == "DEPTSALES")
select new DeptSales
{
Dn = (int)d.Number,
Dnm = "Mens",
On = d.OutletNo,
Qs = (double)d.Value_4,
Se = (double)d.Value_2,
Si = (double)d.Value_3
};
Thanks once again.

Shorten where clauses

I have multiple tables which are combined with a members table on a one to one basis, the two columns I want to extract are the name from the members table and the test from the test table.
The test column is nvarchar() and has the possible entries of "P", "F", null, "", a Partial score such as (26.5) or a decimal number below 100. The following code almost does the job but it looks clunky with so many where clauses.
Also the output is ordered descending but lists double digit number after single numbers such as :
9.0, 9.0, 9.0, 91.4, 8.9, 8.8, 8.8, 86.3, 7.9...etc it seems to descend the numbers on the first digit.
var tests = from t in dc1.testLevels
join m in dc1.Members
on t.testCode equals m.memCode
where !t.Final.Equals("P") && // previous year pass
!t.Final.Equals("F")&& // previous year fail
!t.Final.Equals(null)&& // null values
!t.Final.Equals("") && // empty value
!t.Final.Contains("(") // partial value ie..(26)
select new {Member = m.MemName, Current = Convert.ToDecimal(t.Final)};
var outTest = from tr in tests
orderby tr.Current descending
select new { Member = tr.Member, Current = trCurrent};
dgv1.DataSource = outTest;
It looks like you're trying to only get the results that are decimal numbers only. Instead of blacklisting it to remove what you aren't looking for, I would instead whitelist it.
I think it would be easier to convert it to fluid notation so that you can create a Where clause that would look for only decimal numbers:
var tests = dc1.testLevels
.Where (t => {decimal dec; return decimal.TryParse(t.Final, out dec);})
.Join(dc1.Members, t => t.testCode, m => m.memCode,
(t,m) => new { Member = m.memCode, Current = Convert.ToDecimal(t.Final) })
.OrderByDescending (x => x.Current);
Also notice that this allows you to put your OrderBy clause at the end which will order your results numerically and not alphabetically like you were doing before.
EDIT
After some further thought, I worked this out in query notation like you have it. Also note how the orderby clause has changed:
decimal deci;
var tests = from t in dc1.testLevels
let IsDecimal = decimal.TryParse(t.Final, out deci)
where IsDecimal == true
join m in dc1.Members
on t.testCode equals m.memCode
orderby Convert.ToDecimal(t.Final) descending
select new {Member = m.MemName, Current = Convert.ToDecimal(t.Final)};
EDIT
Since those solution will not work in Linq-To-SQL you are limited to what you can do. The solution that the commenters to your question have given is this:
var ignoreList = new List<string>
{
"P",
"F",
null,
""
};
var tests = from t in dc1.testLevels
join m in dc1.Members
on t.testCode equals m.memCode
where !ignoreList.Contains(t.Final)
where !t.Final.Contains("(") // partial value ie..(26)
orderby Convert.ToDecimal(t.Final) descending
select new {Member = m.MemName, Current = Convert.ToDecimal(t.Final)};

Group Number in a LINQ Group by Query

I've been using 101 LINQ Samples to get my feet wet using LINQ. It's been a good first resource, but I can't see an example there of what I currently need.
I just need to associate a sequential group number with each group. I have a working solution:
var groups =
from c in list
group c by c.Name into details
select new { Name = details.Key, DetailRecords = details };
int groupNumber = 0;
foreach (var group in groups)
{
//
// process each group and it's records ...
//
groupNumber++;
}
But, I'm sure it's possible to use LINQ to also generate the groupNumber. How?
This depends on your exact needs, but you can use:
var groupArray = groups.ToArray();
Similarly, you can use ToList. These data structures are sequential, and each group has an index.
If you do need the index on the object you create, another option is to use Select:
list.GroupBy(c => c.Name)
.Select((details, ind) =>
new
{
Name = details.Key,
DetailRecords = details,
Index = ind
});
this should do the trick:
int groupNumber = 0;
var groups =
from c in list
group c by c.Name into details
select new { Name = details.Key, DetailRecords = details, grpNum = groupNumber++};
if it's just a sequential group number, just use the Count() method on your IEnumerable.
var groups =
from c in list
group c by c.Name into details
select new {Name = details.Key, DetailRecords = details};
for(int i = 0; i < groups.Count(); i++)
{
//Process Records
}
Then, if you need the specific group number, you can just grab i.

Categories

Resources