Filtering this Linq query - c#

I want to use this query:
var queryData = from va in xdoc.Descendants("language")
select new
{
StringID = va.Parent.Parent.Attribute("id").Value,
Language = va.Attribute("name").Value,
LanguageData = va.Element("value").Value,
};
var organizedData = from x in queryData
group x by x.StringID into xg
select new
{
StringID = xg.Key,
English = xg.SingleOrDefault(x => x.Language == "ENGLISH_US").LanguageData,
Custom = xg.SingleOrDefault(x => x.Language == languageBox.SelectedItem.ToString()).LanguageData,
};
mainView.DataSource = organizedData.ToList();
mainView.Refresh();
except that as an additional condition for what is retrieved for the Custom anonymous type, its value must be equal to "*".
Why can't I figure this out? I guess I don't know enough about anonymous types or the => operator.

Is that what you want?
mainView.DataSource = organizedData.Where(x => x.Custom == "*").ToList();

I think this is what you're looking for. I put the value in a temp variable so it doesn't have to be computed twice.
var organizedData = from x in queryData
group x by x.StringID into xg
let temp = xg.SingleOrDefault(x => x.Language == languageBox.SelectedItem.ToString()).LanguageData
where temp == "*"
select new
{
StringID = xg.Key,
English = xg.SingleOrDefault(x => x.Language == "ENGLISH_US").LanguageData,
Custom = temp,
};

Related

returning multiple column and sum using linq expression

I need to return two fields using a lambda expression. The first one is the sum of the amount field and the second one is CurrentFinancial year. Below is the code that I have written, how do I include CurrentFinancialYear?
var amount = dealingContext.vw_GetContribution
.Where(o => o.ContactID == contactId)
.Sum(o => o.Amount);
return new Contribution { Amount = amount ?? 0, CurrentFinancialYear = };
Grouping by Year should do the trick:
from entry in ledger.Entries
where entry.ContactID == contactId
&& entry.Time.Year == currentFinancialYear
group entry by entry.Time.Year
into g
select new Contribution ()
{
Amount = g.ToList ().Sum (e => e.Amount),
CurrentFinancialYear = g.Key
};
UPDATE - just return the first/default result...
(from entry in ledger.Entries
where entry.ContactID == contactId
&& entry.Time.Year == currentFinancialYear
group entry by entry.Time.Year
into g
select new Contribution ()
{
Amount = g.ToList ().Sum (e => e.Amount),
CurrentFinancialYear = g.Key
}).FirstOrDefault();
First of all use a simple select
var contribution = dealingContext.vw_GetContribution
.Where(o => o.ContactID == contactId).ToList();
It will give you a list of type vw_GetContribution
Then use groupby on this list as
var groupedContribution = contribution.GroupBy(b => b.CurrentFinancialYear).ToList();
Now you can iterate through or use this list as
foreach(var obj in groupedContribution.SelectMany(result => result).ToList())
{
var amount = obj.Amount;
var Year = obj.CurrentFinancialYear;
}
OR
In single line, you can do all the above as
var contList = context.vw_GetContribution
.Select(a => new { a.Amount, a.CurrentFinancialYear })
.GroupBy(b => b.CurrentFinancialYear)
.SelectMany(result => result).ToList();
I hope this will solve your problem.
Can you try this:
var amount = dealingContext.vw_GetContribution
.Where(o => o.ContactID == contactId)
.GroupBy(o=> new { o.CurrentFinancialYear, o.Amount})
.Select(group =>
new {
year= group.Key.CurrentFinancialYear,
sum= group.Sum(x=>x.Amount)
});

Get all if variable is null else get matching

Can't figure out the logic for Get all records if variable is null else get where officername = officer.
var res = (from h in db.BalanceHistories
where temp.Contains(h.LoanType ?? 0)
&& ((officer != null && h.OfficerName.ToLower() == officer.ToLower()) || ("Get all records"))
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
}).ToList();
While you can make a compound if statement, this will (usually -- currently always) pass this compound statement on to the database. In many cases, this can cause index misses which if done correctly wouldn't be missed. In non-Microsoft SQL servers, these types of queries are also known to just plain not work (MySQL, DB2). It's better to just write the query correctly in the first place:
var query = db.BalanceHistories
.Where(h=>temp.Contains(h.LoanType ?? 0));
if (officer!=null)
{
// Depending on your database, the ToLower()s here may not be needed.
query=query.Where(h=>h.OfficerName.ToLower() == officer.ToLower()))
}
var res=(from h in query
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
});
Just swap ("Get all records") with (officer == null), Although i would suggest you to put this condition at first.
Explanation:
If officer == null than respect to short circut law we will return true and the rest of our condition won't matter.
Else means officer != null and thus we want to check if it matches our h.OfficerName data.
End result:
res = (from h in db.BalanceHistories
where temp.Contains(h.LoanType ?? 0)
&& (
officer == null
|| h.OfficerName.ToLower() == officer.ToLower())
)
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
}).ToList();
Have you tried:
var res = (from h in db.BalanceHistories
where temp.Contains(h.LoanType ?? 0)
&& ((officer == null) || (h.OfficerName.ToLower() == officer.ToLower()))
group h by new { h.Date.Value.Month, h.Date.Value.Year } into p
select new
{
Month = p.Key.Month,
Year = p.Key.Year,
Count = p.Count(),
Balance = p.Sum(x => x.Balance),
Delinquent = p.Sum(x => x.Delinquent)
}).ToList();

Lambda expression where id in list of ids

I have 2 lists
var listquestionold = db.tblExamQuetions.Where(p => p.QuetionExamId == oldexamid).ToList();
var listquestionnew = listquestionnew = db.tblExamQuetions.Where(p => p.QuetionExamId == examid ).ToList();
List<tblExamQuestionAnswers> listanswers = new List<tblExamQuestionAnswers>();
How can I get answers where questionId is in listquestionold:
listanswers =db.tblanswers.where(p=> p.ExamQuestionId exists in listquestionold ?
It's easy with Contains method of the List:
var listquestionold = db.tblExamQuetions.Where(p => p.QuetionExamId == oldexamid).ToList();
var listanswers = db.tblanswers.Where(w => listquestionold.Contains(w.ExamQuestionId)).ToList();

Combine results from multiple queries to as single queryable

I want to search through a user database and order my results according to how precise the match is. Exact matches on a users name should appear in the result before single word matches, as an example.
This is what i have (the variable 'value' contains a search term and 'query' contains an initial queryable i want to modify)
var values = value.Split(new [] {' ','\t', '\n', '\r'});
var q1 = query.Where(u => u.Id == valueAsInt || u.ExternalId == valueAsInt);
var q2 = query.Where(u => u.Name.Contains(value) || u.Username.Contains(value));
var q3 = query.Where(u => values.All(i => u.Name.Contains(i)) || values.All(i => u.Username.Contains(i)));
var q4 = query.Where(u => values.Any(i => u.Name.Contains(i)) || values.Any(i => u.Username.Contains(i)));
However, I now want to combine the results of q1 through q4 and have a new queryable which i can pass along. I also want to preserve the order of my queries, and frankly I have no idea how to go about doing this..
Answered by Silas Hansen in the comments
You should use ranking. e.g.
var result = query.Select(u =>
{
if (u.Id == valueAsInt || u.ExternalId == valueAsInt)
return new {Rank = 1, Item = u};
if (u.Name.Contains(value) || u.UserName.Contains(value) )
return new {Rank = 2, Item = u};
//Add the other conditions in here
return new {Rank = 3, Item = u};
}).OrderBy(u => u.Rank).Select(u => u.Item);

LINQ-to-SQL - 'Sum' inside a select new

I have a LINQ-to-SQL query that runs through a table, that I want to select 3 sum's - the sums of 'Rate' and 'AdditionalCharges', so I have something like this:
var sums = from d in dc.Deliveries
where d.TripDate == DateTime.Now
select new
{
Rate = d.Rate,
AdditionalCharges = d.AdditionalCharges
};
However, obviously this returns a new row for every delivery, which means I have to sum them up afterwards - which seems fairly inefficient. Is there an easier way?
I know that this is an old question, but hey, I found it, so hopefully this will help someone else...
You can also do this using Fluent syntax:
var sums = dc.Deliveries
.Where(d => d.TripDate == DateTime.Now)
.GroupBy(d => d.TripDate)
.Select(g =>
new
{
Rate = g.Sum(s => s.Rate),
AdditionalCharges = g.Sum(s => s.AdditionalCharges)
});
Hope this helps someone...
If you use query syntax you can do something like the following
var data = dc.Deliveries.Where(d => d.TripDate == DateTime.Now)
var rateSum = data.Sum(d => d.Rate);
var additionalCharges = data.Sum(d => d.AdditionalCharges);
this is off the top of my head and not tested
Not sure but you can try out the group bye function as below
var sums = from d in dc.Deliveries
where d.TripDate == DateTime.Now
group d by new {d.Rate,d.AdditionalCharges,d.TripDate} into g
select new
{
Rate = g.Sum(s => s.Rate ),
AdditionalCharges = g.Sum(s => s.AdditionalCharges)
};
You should be able to do this:
DateTime d = DateTime.Now;
var sums = from d in dc.Deliveries
select new
{
Rate = dc.Deliveries.Where(n => n.TripDate == d).Sum(n => n.Rate),
AdditionalCharges = dc.Deliveries.Where(n => n.TripDate == d).Sum(n => n.AdditionalCharges)
};
var result = sums.FirstOrDefault();
var sums = from d in dc.Deliveries
where d.TripDate == DateTime.Now
Group by d.TripDate // or primary key
Into TotalRate = sum(d.Rate),
TotalAdditionalCharges = sum(d.AdditionalCharges)
Select TotalRate , TotalAdditionalCharges

Categories