IGrouping does not contain a definition for Sum - linq

Would anyone have an idea what's up here? I'm loading an XML file, parsing it and using LINQ to get some summary info. Here's the XML document:
<?xml version="1.0" encoding="utf-8"?>
<root>
<Ticker>
<Name>MSFT</Name>
<PurchaseDate>
2009-01-01
</PurchaseDate>
<Shares>44</Shares>
</Ticker>
<Ticker>
<Name>MSFT</Name>
<PurchaseDate>
2009-03-01
</PurchaseDate>
<Shares>33</Shares>
</Ticker>
<Ticker>
<Name>GOOG</Name>
<PurchaseDate>
2009-03-01
</PurchaseDate>
<Shares>122</Shares>
</Ticker>
<Ticker>
<Name>AAPL</Name>
<PurchaseDate>
2019-03-01
</PurchaseDate>
<Shares>89</Shares>
</Ticker>
</root>
My code:
var xmlStr = File.ReadAllText("ClientInfo.xml");
var Summary = XElement.Parse(xmlStr);
var data = from acct in Summary.Elements("Ticker")
select new
{
Ticker = (string)acct.Element("Name"),
Shares = (int)acct.Element("Shares")
};
var groupedDataByTicker = from acct in data
group acct by acct.Ticker into g
select new
{
Ticker = g.Key,
Shares = g.Sum(),
};
Works fine but when I add the g.Sum() bit I get this message:
'IGrouping>' does not contain a definition for 'Sum' and the best extension method overload 'Queryable.Sum(IQueryable)' requires a receiver of type 'IQueryable'
I can't make sense of it, what am I doing wrong?

In your code, you are trying to find the sum of the group itself.
Instead, you should be summing by the Shares property:
var groupedDataByTicker = from acct in data
group acct by acct.Ticker into g
select new
{
Ticker = g.Key,
Shares = g.Sum(row => row.Shares),
};

Related

first_or_initialize is not working for relative model and creating new record each time

ccs.each do |cd|
relative_model = main_model.relative_model.where(start_date: XYZ, end_date: XYZ).first_or_initialize
relative_model.capacity = cd['capacity'].to_f
relative_model.save!
end
As per above code, first_or_initialize is not working for relative model and creating new record each time.
Here is the query run at background for both inr:
SELECT `capacity_commitments`.* FROM `capacity_commitments` WHERE `capacity_commitments`.`participants_subscription_id` = 1 AND `capacity_commitments`.`start_date` = '2016-11-16' AND `capacity_commitments`.`end_date` = '2016-11-21'
SELECT `capacity_commitments`.* FROM `capacity_commitments` WHERE `capacity_commitments`.`participants_subscription_id` = 1 AND `capacity_commitments`.`start_date` = '2016-11-16' AND `capacity_commitments`.`end_date` = '2016-11-21'
NEED INITIAL HELP OR POINT OUT WHAT IS WRONG IN ABOVE CODE?
Try to use find_or_initialize_by method
relative_model = main_model.relative_model.find_or_initialize_by(start_date: XYZ, end_date: XYZ)

Doing Sum() on a set of anonymous type: is it possible?

If I select an anonymous type (select new) from a query:
var smsPerGroup = from g in db.Groups
select new
{
GroupName = g.Name,
ReceivedSMS = g.Members.SelectMany(p => p.ReceivedSMS).Count()
};
It happends that I can't sum() on it:
int max = smsPerGroup.Max(g => g.ReceivedSMS); // ERROR!
The error thrown is:
There was an error parsing the query.
What is the most correct solution for this?
I don't want to create a class to use ONLY one time, on this query.
Is it possible to have a "not very anonymous" type? this is: to define the type of its properties but not the type of the class itself
Something like this: (which is syntactically incorrect)
...
select new
{
string GroupName = g.Name,
int ReceivedSMS = g.Members.SelectMany(p => p.ReceivedSMS).Count()
};
Edit: the error in detail is the following
There was an error parsing the query. [ Token line number = 6,Token line offset = 5,Token in error = SELECT ]
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlServerCe.SqlCeException: There was an error parsing the query. [ Token line number = 6,Token line offset = 5,Token in error = SELECT ]
Source Error:
Line 159: };
Line 160:
Line 161: int max = smsPerGroup.Max(g => g.ReceivedSMS);
A simple solution would be to materialize the query with .ToList() before calling .Sum():
var test = (from g in db.Groups
select new
{
GroupName = g.Name,
ReceivedSMS = g.Members.SelectMany(p => p.ReceivedSMS).Count()
}).ToList();
var sum = test.Sum(t => t.ReceivedSMS);

SharePoint 2013 - Sorting Search Results not working (KeywordQuery-SortList)

am using KeywordQuery to search and.. the SortList does not affect result, it is always return first 5 results. Any suggestion? The code is bellow...
using (KeywordQuery query = new KeywordQuery(site))
{
var fedManager = new FederationManager(application);
var owner = new SearchObjectOwner(SearchObjectLevel.SPSite, site.RootWeb);
query.SourceId = fedManager.GetSourceByName("NewsRS", owner).Id;
query.QueryText = string.Format("WorkflowStatusOWSCHCS:Approved PublishedUntilDate>=\"{0}\" OR NewsNewsPublishedDate<=\"{0}\"", DateTime.Now);
query.KeywordInclusion = KeywordInclusion.AllKeywords;
query.RowLimit = 5;
query.StartRow = 1;
query.SelectProperties.Add("NewsFriendlyUrl");
query.SelectProperties.Add("NewsNewsTeaser");
query.SelectProperties.Add("NewsNewsDate");
query.SelectProperties.Add("NewsPublishedUntilDate");
query.SelectProperties.Add("NewsNewsContent");
query.SelectProperties.Add("NewsNewsPublishedDate");
query.SelectProperties.Add("NewsNewsImage");
query.SortList.Add("NewsNewsDate", SortDirection.Descending);
var searchExecutor = new SearchExecutor();
var myResults = searchExecutor.ExecuteQuery(query);
}
}
... the NewsNewsDate is marked as Sortable
query.RowLimit = 5; => You are explicitly specifying the Rowlimit to be 5. That is why it returns the first 5 results always. Change the rowlimit and set it to the number of results you need.

Get a value using Ling to XML and where clause

I want to use Linq to XML and I am trying to figure out to way to get the value for currency CAD, BuyRateForeign, basically I need to get value 5,602895.
<ExchRates>
<ExchRate>
<Bank>Bank</Bank>
<CurrencyBase>USD</CurrencyBase>
<Date>24.05.2013.</Date>
<Currency Code="036">
<Name>AUD</Name>
<Unit>1</Unit>
<BuyRateCache>5,569450</BuyRateCache>
<BuyRateForeign>5,625707</BuyRateForeign>
<MeanRate>5,711378</MeanRate>
<SellRateForeign>5,797049</SellRateForeign>
<SellRateCache>5,855019</SellRateCache>
</Currency>
<Currency Code="124">
<Name>CAD</Name>
<Unit>1</Unit>
<BuyRateCache>5,546866</BuyRateCache>
<BuyRateForeign>5,602895</BuyRateForeign>
<MeanRate>5,688218</MeanRate>
<SellRateForeign>5,773541</SellRateForeign>
<SellRateCache>5,831276</SellRateCache>
</Currency>
</ExchRate>
</ExchRates>
var xDoc = XDocument.Load("path/to/your.xml");
var cadForeignBuyRate =
xDoc.Root.Element("ExchRate").First(e => e.Element("Bank").Value == "Bank")
.Elements("Currency").First(e => e.Element("Name").Value == "CAD")
.Element("BuyRateForeign").Value;
var xDoc = XDocument.Load("path/to/your.xml");
var BuyRateForeign = from nm in xDoc.Descendants("Currency")
where (string)nm.Element("Name") == "CAD"
select (string)nm.Element("BuyRateForeign");
Using Lambda expression
var stringRate = xDoc.Descendants("Currency")
.Where(p=> (string)p.Element("Name") == "CAD")
.Select(p => (string)p.Element("BuyRateForeign"))
.SingleOrDefault();

Calculate time interval between 2 dates on different rows

I have login and logout events and i need to calculate time between them.
I guess i could group each 2 rows (each two messages) and then do the calculation, but how would you do that?
Example XML i need to query:
<Log>
<Message>
<DateTime>2009-12-02 14:38:41</DateTime>
<Priority>Local3.Info</Priority>
<Source_Host>192.168.0.100</Source_Host>
<MessageText>Dec 2 14:38:41 root: login,ng1,192.168.0.160,janis.veinbergs</MessageText>
</Message>
<Message>
<DateTime>2009-12-02 15:28:19</DateTime>
<Priority>Local3.Info</Priority>
<Source_Host>192.168.0.100</Source_Host>
<MessageText>Dec 2 15:30:33 root: logout,ng1,,janis.veinbergs</MessageText>
</Message>
<Message>
<DateTime>2009-12-02 15:29:11</DateTime>
<Priority>Local3.Info</Priority>
<Source_Host>192.168.0.100</Source_Host>
<MessageText>Dec 2 15:31:25 root: login,ng1,192.168.0.160,janis.veinbergs</MessageText>
</Message>
<Message>
<DateTime>2009-12-02 15:58:22</DateTime>
<Priority>Local3.Info</Priority>
<Source_Host>192.168.0.100</Source_Host>
<MessageText>Dec 2 16:00:37 root: logout,ng1,,janis.veinbergs</MessageText>
</Message>
</Log>
Thankyou.
Given SQL doesn't have any aggregate Diff method, I would suggest joining the table onto itself, and selecting each row that you're after from each side of the join.
Something like:
var diff = from a in db.Events
join b in db.Events on a.SessionId equals b.SessionId
where a.EventType == 'Login' && b.EventType == 'Logout'
select b.EventTime - a.EventTime;
Haven't tried this, but something along those lines should work.
EDIT: updated to suit new provided info.
Try the following. Could perhaps be more concise, but does the job. Have broken down into a couple of queries for easier reading.
var query = from a in (from log in data.Elements()
select new {
date = DateTime.Parse(log.Element("DateTime").Value),
msg = log.Element("MessageText").Value
})
select new {
a.date,
type = a.msg.Contains("login") ? "Login" : "Logout",
user = a.msg.Substring(a.msg.LastIndexOf(',') + 1)
};
var results = from a in query
join b in query on a.user equals b.user
where a.type == "Login" && b.type == "Logout"
&& b.date == (query.OrderBy(o => o.date).Where(d => d.date > a.date).FirstOrDefault().date)
select new {
a.user,
Login = a.date,
Logout = b.date
};

Resources