how to only query newest version? - c#

The following query gives me a barcode, version no of that barcode and an appcode. I would need the query to filter out duplicate barcodes and only keep the highest version number of that barcode.
I've been thinking along the way of merging the barcode field and the version field and only keep the highest but that seems dirty. Is there a cleaner solution?
select Barcode, MAX(versionNo) vn, Appcode from Mailsort
where Created between '01/26/2011' and '01/27/2011'
group by Barcode, AppCode;
The reason for this query is to get a LINQ statement.This does a count for every appcode regardless of the barcodes or the version at thye moment.
var results = from p in dataContext.GetTable<mailsortEntity>()
where p.Created > datetime && p.Created < datetime.AddDays(1)
group p by new { p.AppCode } into g
select new AppCodeCountEntity
{
AppCode = g.Key.AppCode,
Count = g.Count()
};
Is there a better solution than this LINQ code above?

var maxQuery =
from rh in MailSort
group rh by rh.BarCode into latest
select new { BarCode = latest.Key, MaxVersion = latest.Max(l => l.Version) }
;
var query =
from rh2 in MailSort
join max in maxQuery on new {rh2.BarCode, Version = rh2.Version }
equals new { max.BarCode, Version = max.MaxVersion }
select new { rh2.BarCode, rh2.Version, rh2.AppCode }
;
var barCodes = query.ToList();

Related

linq and DTO property interpolation

In the below query I order by "Category1":
var ExampleValues = (from values in ExampleAllRecorsds
group values by new { values.Category1, values.Date.Value.Month } into x
orderby x.Key.Category1
select new ExamplesDto()
{
ExampleId = exampleId,
Row = x.Key.Category1,
Month = x.Key.Month,
}).ToList();
I have other properties that I want to order my query by, depending on another variable. It could be ordering by Category2, Category3, etc.
What I want to do is change the ordering of this query between my CategoryX properties without needing to wholesale repeat the query in a switch statement.
For example, this is how I would think to do it with a switch. Notice that this is repeating a lot of code.
switch(categoryVar){
case "Category1":
var ExampleValues = (from values in ExampleAllRecorsds
group values by new { values.Category1, values.Date.Value.Month } into x
orderby x.Key.Category1 // the only change
select new ExamplesDto()
{
ExampleId = exampleId,
Row = x.Key.Category1,
Month = x.Key.Month,
}).ToList();
break;
case "Category2":
var ExampleValues = (from values in ExampleAllRecorsds
group values by new { values.Category1, values.Date.Value.Month } into x
orderby x.Key.Category2 // the only change
select new ExamplesDto()
{
ExampleId = exampleId,
Row = x.Key.Category2,
Month = x.Key.Month,
}).ToList();
break
...
}
How do I not repeat myself?
If you don't mind using an extra library and are on .net Core you could try:
System.Linq.Dynamic.Core
I'm pretty sure there is a System.linq.dynamic for Framework as well, you can check nuget for both

ORA-00907: missing right parenthesis in LINQ

I have Linq query where I am trying to write subquery to set the value of item, I am encountering with error saying
{ORA-00907: missing right parenthesis
}, Please let me know the right syntax to make it work
var lst = (
from cr in dbContext.Company
orderby cr.COMPANY_KEY
select new CompanyDto()
{
CompanyKey = cr.CompanyKey,
CompanyCode = (from rc in dbContext.COMPANY_PORTFOLIOS where rc.PORTFOLIO == cr.P_PORTFOLIO select rc.COMPANY_CODE).FirstOrDefault()
}
);
var d = st.Skip(pageIndex).Take(pageSize).ToList();
Even the below piece of code is not working
var lst = (
from cr in dbContext.Company
orderby cr.COMPANY_KEY
select new CompanyDto()
{
CompanyKey = cr.CompanyKey,
CompanyCode = (from rc in dbContext.COMPANY_PORTFOLIOS where rc.PORTFOLIO == cr.P_PORTFOLIO select rc.COMPANY_CODE).Single()
}
);
var d = st.Skip(pageIndex).Take(pageSize).ToList();
I think you can just use a Join to achieve what you are looking to do:
var lst = (
from cr in dbContext.Company
orderby cr.COMPANY_KEY
join rc in dbContext.COMPANY_PORTFOLIOS on cr.PORTFOLIO equals rc.P_PORTFOLIO into myJoin
from rc in myJoin.DefaultIfEmpty()
select new CompanyDto()
{
CompanyKey = cr.CompanyKey,
CompanyCode = rc.COMPANY_CODE
}
);
var d = lst.Skip(pageIndex).Take(pageSize).ToList();
If the above still gives Oracle errors, put a breakpoint at the last line and get the SQL the linq generates. You can then paste this into something like Oracle SQL Developer and run the query, which may give you a more informative error message and allow you to track down the issue.

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.

LINQ group by month question

I'm new to LINQ to SQL and I would like to know how to achieve something like this in LINQ:
Month Hires Terminations
Jan 5 7
Feb 8 8
Marc 8 5
I've got this so far, and I think there is something wrong with it but I'm not sure:
from term1 in HRSystemDB.Terminations
group term1 by new { term1.TerminationDate.Month, term1.TerminationDate.Year } into grpTerm
select new HiresVsTerminationsQuery
{
Date = Criteria.Period,
TerminationsCount = grpTerm.Count(term => term.TerminationDate.Month == Criteria.Period.Value.Month),
HiresCount = (from emp in HRSystemDB.Persons.OfType<Employee>()
group emp by new { emp.HireDate.Month, emp.HireDate.Year } into grpEmp
select grpEmp).Count(e => e.Key.Month == Criteria.Period.Value.Month)
});
Thanks in advance.
I'm not quite sure where does the Criteria.Period value come from in your sample query.
However I think you're trying to read both hires and terminations for all available months (and then you can easily filter it). Your query could go wrong if the first table (Termination) didn't include any records for some specified month (say May). Then the select clause wouldn't be called with "May" as the parameter at all and even if you had some data in the second table (representing Hires), then you wouldn't be able to find it.
This can be elegantly solved using the Concat method (see MSDN samples). You could select all termniations and all hires (into a data structure of some type) and then group all the data by month:
var terms = from t in HRSystemDB.Terminations
select new { Month = t.TerminationDate.Month,
Year = term1.TerminationDate.Year,
IsHire = false };
var hires = from emp in HRSystemDB.Persons.OfType<Employee>()
select new { Month = emp.HireDate.Month,
Year = emp.HireDate.Year
IsHire = true };
// Now we can merge the two inputs into one
var summary = terms.Concat(hires);
// And group the data using month or year
var res = from s in summary
group s by new { s.Year, s.Month } into g
select new { Period = g.Key,
Hires = g.Count(info => info.IsHire),
Terminations = g.Count(info => !info.IsHire) }
When looking at the code now, I'm pretty sure there is some shorter way to write this. On the other hand, this code should be quite readable, which is a benefit. Also note that it doesn't matter that we split the code into a couple of sub-queries. Thanks to lazy evalutation of LINQ to SQL, this should be executed as a single query.
I don't know if it shorter but you can also try this version to see if it works better with your server. I don't know exactly how these two answers turn into SQL statements. One might be better based on your indexs and such.
var terms =
from t in Terminations
group t by new {t.Month, t.Year} into g
select new {g.Key, Count = g.Count()};
var hires =
from p in Persons
group p by new {p.Month, p.Year} into g
select new {g.Key, Count = g.Count()};
var summary =
from t in terms
join h in hires on t.Key equals h.Key
select new {t.Key.Month, t.Key.Year,
Hires = h.Count, Terms = t.Count};

Convert SQL to linq expression with count

I am trying to convert the following SQL into a LINQ expression
SELECT COUNT(ID) AS Count, MyCode
FROM dbo.Archive
WHERE DateSent>=#DateStartMonth AND DateSent<=#DateEndMonth
GROUP BY MyCode
and I have been trying to follow this webpage as an example:
Converting SQL containing top, count, group and order to LINQ (2 Entities)
I got this so far but I am stuck on understanding the new part
var res = (from p in db.Archives
where (p.DateSent>= dateStartMonth) && (p.DateSent< dateToday)
group p by p.MyCode into g
select new { ??????MyCode = g.something?, MonthlyCount= g.Count() });
Thanks in advance for helping
UPDATE:
can you explain what g.Key is? I dont understand where that variable came from or what it is referring too? I mean what if I group on 4 different things? How would I refer to each one?
var res = from archive in db.Archives
where archive.DateSent >= dateStartMonth &&
archive.DateSent < dateToday
group archive by archive.MyCode, archive.Extra into archiveGrp
select new
{
MyCode = archiveGrp.Key,
Extra = archiveGrp.???
MonthlyCount = archiveGrp.Count()
};
The LINQ statement below should work:
var res = from archive in db.Archives
where archive.DateSent >= dateStartMonth &&
archive.DateSent < dateToday
group archive by archive.MyCode into archiveGrp
select new
{
MyCode = archiveGrp.Key,
MonthlyCount = archiveGrp.Count()
};
Notice that the Key property will contain the value of the property that you group on, in this case MyCode.
from p in archive
where p.DateSent >= dateStartMonth && p.DateSent < dateToday
group p by p.MyCode into g
select new { Count = g.Count(), MyCode = g.Key }
produces the same output as your Sql in Linqpad

Categories

Resources