I am learning about RSS feeds and I have hit a problem which I am surprised I have never had before now, it is probably a very simple answer but I can't find anything on Google. I am using SyndicationItem to get the XML items from an RSS feed but when you use foreach it takes every item, I only want to get the latest item - the code snippet is below.
//Add required parsing in here
foreach (SyndicationItem item in feed.Items)
{
//put data you want parsed
}
Obviously I have thought of just adding a break at the end, but this is definitely something I will need to find an answer for in the future and I would like to resolve it much cleaner than that.
So any help here would be appreciated, thanks!
Try this:
var latest = feed.Items.OrderByDescending(x=>x.PublishDate).FirstOrDefault();
OrderByDescending will order items by date descending and taking FirstOrDefault item will get item with highest publish date (latest item)
SyndicationItem has PublishDate property
Read more about Linq it's very usefull creating such queries.
EDIT:
if they are sorted by PublishDate you can use LastOrDefault method, but if you are not 100% sure about that it's better to sort it before.
var latest = feed.Items.LastOrDefault();
EDIT2:
handle empty lists like:
if(!feed.Items.Any)
{
//alert about no elements
}
Related
Say, I have collection People. How should I fetch first 1000 documents that doesn't have a field Phone? As I understand, I should use $exists however I cannot understand how to use it from .NET driver and there is next to no info on that topic on the internet. Any help will be appreciated. Thanks!
Assume your Model Class is Model and colelction name is "Model".
var coll = db.GetCollection<Model>("Model");
var ret = coll.Find(Builders<Model>.Filter.Exists(d => d.Phone, false))
.Limit(1000)
.ToList();
With ToList you will get already loaded list, sometimes it's better to use ToEnumerable and have enumerable to iterate.
I have a Droplist field in an item that contains other items which are under the path /sitecore/content/Home. I need to get the selected item from the Droplist.
In this situation, I have to get the selected Item by its name. Are there any other efficient ways of doing this, or is the way I am doing this okay?
public static Item GetItemByName(string itemName)
{
Database masterDb = Factory.GetDatabase("master");
Item homeItem = masterDb.GetItem("/sitecore/content/Home");
return homeItem.Axes.GetDescendants().FirstOrDefault(p => p.Name == itemName);
}
Droplist is not the luckiest choice here. You should use Droplink instead - it stores the item as ID, instead of storing item name only.
You should avoid using name as item identifier. There can be multiple items with the same name, even under same parent.
homeItem.Axes.GetDescendants() is not really efficient method. It gets all the items which are under that node. You should avoid using it.
If you know that the item will be a child of the homeItem, you can use:
homeItem.Children.FirstOrDefault(p => p.Name == itemName)
If that item can be at any level under the homeItem, you can try to use index to get that item (checking item name equals to specified name and item full path starts with home page full path).
This more of an information note than the answer .. #Marek 's answer is absolutely correct that you should use a DropLink instead so that you address the ID of the item directly.
Never (never! Never!) use GetDescendants in a call such as this (ie from Home downwards).I would try and avoid using it anywhere, ever :) [If i could burn GetDescendants out of the API I would :P]
If you think about it, you are starting at the Home node and then iterating down, visiting every single item as you go and it wont stop until it has touched every item, pulled every item from the DB and interrogated it. On a small dev site this opertation will be fast but as your solution gets bigger and bigger, as content editors create more and more items you will find you solution gets slower and slower and your SQL Server get more and more load (and you likely wont immediately know why !)
If you need to do a larger ranging query (i.e. to check a field on every item under the home node) then you should look at Sitecore's ContentSearch API as this is massively faster for doing these sorts of operations.
As #Stephen Pope mentioned to most efficient way to search for an Item by Name is via the ContentSearch. I recently gave a simple Content Search example which you can modify for your needs by add the following line to so that it searches Sitecore Item Names to find those with a matching name.
IQueryable<SearchResultItem> query = index.GetQueryable<SearchResultItem>().Where(i => i.Name == itemName).Filter(predicate);
It is also worth following #Marek Musielak's advice and using Droplink over Droplist where possible so the value contained in the field is the ID of an Item instead of its Name which is far more useful in your development.
Most of them have given the answers correctly. I would also suggest the same.
Droplink is always preferable to droplist because it stores the item ID instead of name. Droplink will give you a lot of flexibility over droplist.
GetDescendants - Loop through all the items and check so avoid as much as possible.instead use sitecore queries or fast queries which gives you more efficiency.
masterDb.SelectItems("fast:/sitecore/content/Home//*[##templateid = '{F348C2A0-73B8-4AF4-BD9E-2C5901908369}']");
No one is going to store all the items in the same node. You would have created different type of items under home node. If you want to retrieve a specific set of items,Go for sitecore queries instead of getdescendants.
I would like to know how can I check the existence of two objects with mongoDB and C#.
I know how to do it for 1 object:
foreach (BsonDocument item in collection.Find(Query.Exists("Boiling point")))
But i have no idea how to check on two objects.
Thanks!
You can use Query.And to search more than one condition.
foreach (BsonDocument item in collection.Find(
Query.And(
Query.Exists("Boiling point"),
Query.Exists("Freezing Point")))
A complete list is available in the online documentation here.
I've decided to take a quick look into the LINQ side of things, as opposed to just using a straight up foreach loop, but i'm having some trouble getting it to work, mainly due to datatypes i believe.
So i've got this, so far;
var selectedSiteType = from sites in siteTypeList
where sites.SiteTypeID == temp
select sites;
siteTypeList is a list of SiteTypes. I'm trying to find a particular one (Which i've denounced with variable "temp".
How do i then use this selected SiteType AS a SiteType? When i try and pass "selectedSiteType" through to another function, like so;
mSiteTypeSub.EditSitetype(selectedSiteType);
note: I tried with providing an index, as if selectedSiteType was a list / Array, but that didnt work either, i get the following error:
Argument 1: cannot convert from
'System.Collections.Generic.IEnumerable<DeviceManager_take_2.SiteType>' to
'DeviceManager_take_2.SiteType'
Am i missing something? perhaps a cast of some kind? Like i said i'm new to this and am struggling to get my head around this. Chances are i've got the whole concept wrong and bingbangbosh i've made a fool of myself!
Cheers in advance.
Use First / FirstOrDefault / Single / SingleOrDefault to get an item of the particular type from the collection.
var value = selectedSiteType.First();
// returns the first item of the collection
var value = selectedSiteType.FirstOrDefault();
// returns the first item of the collection or null if none exists
var value = selectedSiteType.Single();
// returns the only one item of the collection, exception is thrown if more then one exists
var value = selectedSiteType.SingleOrDefault();
// returns the only item from the collection or null, if none exists. If the collection contains more than one item, an exception is thrown.
If your return type is a single:
var selectedSiteType = (from sites in siteTypeList
where sites.SiteTypeID == temp
select sites).SingleOrDefault();
If a list (potentially more than one item):
var selectedSiteType = (from sites in siteTypeList
where sites.SiteTypeID == temp
select sites).ToList();
It's the SingleOrDefault / ToList that you're missing from your query.
Shane,
I'm not going to improve on the previous answers. They were both correct. I am going to try and explain a little bit to you, so that you understand it in the future a bit better.
What happens, when you write a piece of code like:
var selectedSiteType = from sites in siteTypeList
where sites.SiteTypeID == temp
select sites;
you don't put the answer into the var (selectedSiteType), instead, you are creating an expression tree, that is evaluated ONLY when you actually use it (in a foreach, or by calling one of the methods (like .First(), .ToList(), SingleOrDefault(), etc).
The default return type of a from statement, is an IEnumerable<>, but if you call the .First() or .SingleOrDefault() (etc), you will dive into that IEnumerable<> and get a specific item.
I hope this helps you better understand what is going on.
Lemme know if I can add anything or if I got anything wrong.
Cheers,
Max
Anyone know how to select a certain amount of items in a List to bind to a DataSource? Basically I'm getting back 10 items (which I don't have control over) and I only need to show 5. Originally I was thinking of using a loop and adding 5 items to a new list but that seems like a lot of code. Is there an expression that I can use to select the first 5?
//Returns a List<DataItem>
MyDataListControl.DataSource = Helper.GetDataItems(); //<= Possible expression?
You may take a look at the Skip and Take LINQ extension methods. So in your case if you wanted to take only the first 5 elements of some IEnumerable<T>:
MyDataListControl.DataSource = Helper.GetDataItems().Take(5).ToList();
What about List's GetRange method? Have you tried that? I don't the internal workings of the method; whether it also creates a new list or not.
GetRange(int index, int count)
Here is the msdn link for it.
RemoveRange will probably be best as you won't have to instanciate a new list, unless that happens internally anyway.. Just make sure you're always getting 10 items or you'll potentially get an ArgumentOutOfRangeException.
list.RemoveRange(5, 5);
That should leave you with the first five items.