I want to build dynamic Linq. Following is my code which works fine for one date. But user can select many dates from calendar. And I need to make Linq for all those selected dates.
saleDate = calendarSales.SelectedDate;
List<SaleDetails> saleDetials = new List<SaleDetails>();
saleDetials = GetSaleDetails();
saleDetials.Where(sale => (Convert.ToDateTime(sale.DATE_TIME).Day == saleDate.Day &&
Convert.ToDateTime(sale.DATE_TIME).Month == saleDate.Month &&
Convert.ToDateTime(sale.DATE_TIME).Year == saleDate.Year)
).ToList();
How to update this query?
You have to build the predicate for your where clause dynamically.
Take a look at the predicatebuilder.
EDIT
Of cause PredicateBuilder supports AND and OR operators.
When using OR you have to start with the initial value of False:
// building the predicate
var pred = PredicateBuilder.False<SaleDetails>();
foreach (var date in MyDateList)
{
pred = pred.Or(sale => sale.DATE_TIME.Date == saleDate.Date);
}
// finally get the data and filter it by our dynamic predicate
List<SaleDetails> saleDetails = GetSaleDetails().Where(pred).ToList();
I'm not sure you need dynamic LINQ here. You should be able to check Where the sale matches Any of the selected dates, like so:
var saleDates = GetSelectedDate();
List<SaleDetails> saleDetials = new List<SaleDetails>();
saleDetials = GetSaleDetails();
saleDetials.Where(sale => saleDates.Any(date =>
(Convert.ToDateTime(sale.DATE_TIME).Day == date.Day &&
Convert.ToDateTime(sale.DATE_TIME).Month == date.Month &&
Convert.ToDateTime(sale.DATE_TIME).Year == date.Year)
)).ToList();
or checking on the Date property:
var saleDates = GetSelectedDate();
List<SaleDetails> saleDetials = new List<SaleDetails>();
saleDetials = GetSaleDetails();
saleDetials.Where(sale => saleDates.Any(date =>
Convert.ToDateTime(sale.DATE_TIME).Date == date.Date)).ToList();
Related
I'm trying to convert this SQL Query into Core EF:
SELECT w.IdShippingBatch, w.BookingNumber, COUNT(c.IdShippingOrder) AS ShippingOrders, w.CreatedOn, w.ModifiedOn
FROM dbo.Shipping`enter code here`Batch AS w LEFT OUTER JOIN
dbo.ShippingOrders AS c ON w.IdShippingBatch = c.IdShippingBatch
WHERE (w.IdCompany = 2) AND (w.IdDealer = 1)
GROUP BY w.IdShippingBatch, w.BookingNumber, w.CreatedOn, w.ModifiedOn
I have tried multiple solutions, including several here. My latest attempt looks like:
var data = (from w in _context.ShippingBatch
join c in _context.ShippingOrders on w.IdShippingBatch equals c.IdShippingBatch into t1
where w.IdCompany == idCompany && w.IdDealer == idDealer
from t2 in t1.DefaultIfEmpty()
group t2 by new { w.IdShippingBatch, w.BookingNumber, w.CreatedOn, w.ModifiedOn } into t3
select new ShippingBatchDTO
{
IdShippingBatch = t3.Key.IdShippingBatch,
BookingNumber = t3.Key.BookingNumber,
ShippingOrders = t3.Count(),
CreatedOn = t3.Key.CreatedOn,
ModifiedOn = t3.Key.ModifiedOn
});
I have also tried adding t3.count(m => m.something != null), but that throws an error.
One major point of EF is to map the relationship between entities so that you can leverage LINQ and let EF compose an SQL query rather than trying to replace SQL with LINQ-QL.
If your ShippingBatch is mapped with a collection of ShippingOrders...
var batches = _context.ShippingBatch
.Where(x => x.IdCompany == idCompany && x.IdDealer == idDealer)
.Select(x => new ShippingBatchDTO
{
IdShippingBatch = x.IdShippingBatch,
BookingNumber = x.BookingNumber,
ShippingOrders = x.ShippingOrders.Count(),
CreatedOn = x.CreatedOn,
ModifiedOn = x.ModifiedOn
}).ToList();
If your ShippingBatch does not have a collection of ShippingOrders, but your ShippingOrder reference an optional ShippingBatch.
var batches = _context.ShippingOrder
.Where(x => x.ShippingBatch != null
&& x.ShippingBatch.IdCompany == idCompany
&& x.ShippingBatch.IdDealer == idDealer)
.GroupBy(x => x.ShippingBatch)
.Select(x => new ShippingBatchDTO
{
IdShippingBatch = x.Key.IdShippingBatch,
BookingNumber = x.Key.BookingNumber,
ShippingOrders = x.Count(),
CreatedOn = x.Key.CreatedOn,
ModifiedOn = x.Key.ModifiedOn
}).ToList();
That should hopefully get you moving in the right direction. If not, expand your question to include details of what you are seeing, and what you expect to see along with definitions for the applicable entities.
I have this loop that builds these IEnumerables one by one, I'd like to be able to optimize this so that it can make the call and build all of these IEnumerables at once in one IEnumerable instead of a list of them as the loop has to do. The code is grouping FilteredCases (cases of different types of trees in one year) by month and calculating the percentage of trees for that month compared to the whole year. My problem is that I am doing this separately for each year and would like to do this in one LINQ call hopefully by grouping the correct data together.
Here's the code:
var seriesDataLineList = new List<IEnumerable<SeriesDataPointArray>>();
foreach (var tree in trees)
{
IEnumerable<SeriesDataPointArray> seriesDataLine = months.Select(month => new SeriesDataPointArray()
{
X = month.LookupMonthName,
Y = new object[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
});
seriesDataLineList.Add(seriesDataLine);
}
My attempt at doing this with LINQ:
var test = from fc in FilteredCases
group fc by new { fc.Tree, fc.Month }
into casesGrouped
orderby casesGrouped.Key.Tree
select new { casesGrouped.Key.Tree, casesGrouped.Key.Month, count = casesGrouped.Count() };
But I'm not sure how to get these into one IEnuerable<SeriesDataPointArray>
What you have above is a mix of loops and linq, which can get confusing because you are mixing iterative with set based logic. If you expand the code out as just loops, you may find it easier to translate to linq.
As all loops
var seriesDataLineList = new List<SeriesDataPointArray>();
foreach (var tree in trees)
{
foreach (var month in months)
{
var seriesDataLine = new SeriesDataPointArray()
{
X = month.LookupMonthName,
Y = new double[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
};
seriesDataLineList.Add(seriesDataLine);
};
}
Once you get the code in all loops, converting to linq is fairly straight forward. Nested loops are functionally equivalent a cartesian product, which syntactically in linq can be achieved by multiple uncorrelated for statements.
var results = from tree in trees
from month in months
select new SeriesDataPointArray()
{
X = month.LookupMonthName,
Y = new double[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
};
Or in lambda, multiple nested select statements. You'll need a SelectMany() in there somewhere to flatten out the nested collections.
var results = trees.Select(tree =>
months.Select(month =>
new SeriesDataPointArray()
{
X = month.LookupMonthName,
Y = new double[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
}
)
).SelectMany(x => x);
My Datatable is in following format.
I want to get the Netfare Where Sector is 1 and then similarly I want to get Netfare Where Sector is 2.
Thanks
You can use the DataTable.Select method to filter the result.
var sector1Results = dt.Select("Sector = 1");
var sector2Results = dt.Select("Sector = 2");
You can also use DataTable.AsEnumerable method to achieve the same
var result1 = dt.AsEnumerable().Where(x => x.Field<int>("Sector") == 1).Select(x => x.Field<int>("Sector1"));
var result2 = dt.AsEnumerable().Where(x => x.Field<int>("Sector") == 2).Select(x => x.Field<int>("Sector2"));
To select the DataRow collection, You can use this
List<DataRow> collection1 = dt.AsEnumerable().Where(x => x.Field<int>("Sector") == 1).ToList();
List<DataRow> collection2 = dt.AsEnumerable().Where(x => x.Field<int>("Sector") == 1).ToList();
You can also merge those condition in single statement (if you want)
List<DataRow> collection = new DataTable().AsEnumerable().Where(x => x.Field<int>("Sector") == 1 || x.Field<int>("Sector") == 2).ToList();
I have some data in an ArrayList and I would like to use that to filter my Linq query using the where clause.
My Linq code below joins two tables and then I filter them using the Where clause. Now I would like to FURTHER filter this query by using the Arraylist as a filter. So the value come from arraylist
I would like the "where" clause to take one more comparison and the value comes from an arraylist:
where rType.Field<string>("ProfSSCMName") == lbProfiles.SelectedValue && rType.Field<string>("Name") == lbHWTypes.SelectedValue && **arrayList.Tostring()**
This is the code that I am using.
Can anyone tell me how can I further filter my Linq query using the values in the arraylist?
joined = from rType in ds.Tables["HWTypes"].AsEnumerable()
join rStock in ds.Tables["Stock"].AsEnumerable()
on rType.Field<string>("ProductID") equals rStock.Field<string>("Partno")
where rType.Field<string>("ProfSSCMName") == lbProfiles.SelectedValue && rType.Field<string>("Name") == lbHWTypes.SelectedValue
select new
{
TagNumber = rStock.Field<string>("TagNumber"),
SerialNumber = rStock.Field<string>("SerialNumber"),
Partno = rStock.Field<string>("Partno"),
PartType = rStock.Field<string>("PartType"),
EcopartSubtype = rStock.Field<string>("EcopartSubtype"),
AzertyQuerty = rStock.Field<string>("Azerty/Querty"),
ProductID = rType.Field<string>("ProductID"),
Name = rType.Field<string>("Name"),
SCCMKeyboard = rType.Field<string>("SCCMKeyboard"),
DisplayName = rType.Field<string>("DisplayName"),
ProfSSCMName = rType.Field<string>("ProfSSCMName"),
TagNameDisplayName = rStock.Field<string>("TagNumber") + " " + rType.Field<string>("DisplayName")
// add the other columns you need here
};
You seem to be using Linq-To-Objects.
So you can just use contains on the arraylist
where rType.Field<string>("ProfSSCMName") == lbProfiles.SelectedValue
&& rType.Field<string>("Name") == lbHWTypes.SelectedValue
&& arrayList.Contains( rType.Field<string>("Name") )
I having a trouble with a query
I need to take out the SHIPMENT from GetAllOrderData - the same place where you can find POD_DATE and RECEIVE_NAME...but I get an error
Error 1 The name 'x' does not exist in the current context
My code is:
public IEnumerable<ReportItemDTO> GetTaskProgress(DateTime targetDate)
{
try
{
var startDate = targetDate.Date;
var endDate = startDate.AddDays(1);
OrderDataRepository rep = new OrderDataRepository();
var query = rep.GetAllOrderData()
.Where(x => x.POD_DATE >= startDate && x.POD_DATE <= endDate)
.GroupBy(o => o.User)
.Select(g => new ReportItemDTO
{
DriverId = g.Key.Id,
PdriverName = g.Key.Name,
OrderCount = g.Count(),
ReportedOrdersCount = g.Count(o => o.RECEIVE_NAME != null),
SHIPMENT = (x.SHIPMENT)
} );
return query;
SHIPMENT = (x.SHIPMENT)
Well you are within a grouping when you try to make that assignment - there are many shipments in each grouping not just one - in fact all shipments for that particular user. Assuming you want a collection of them you could do:
Shipments = g.Select( x=> x.SHIPMENT)
Edit:
If you just want the first shipment for each user (somewhat illogical but fits your data model):
SHIPMENT = g.Select( x=> x.SHIPMENT).First()