What is the best way to get a single object in Linq to Umbraco?
Currently this is what I'm doing:
//Get the project node.
Project project =
(
from projectNode in DigibizDataContext.Projects
where projectNode.Id == Convert.ToInt32(projectId)
select projectNode
).Single();
In usercontrols I would like to use the Linq to Umbraco with the current node (yes I've read this). Is there a better way than this:
//Get the current node.
Content content =
(
from content in DigibizDataContext.Contents where content.Id == currentNodeId select content
).Single();
UmbracoContext.Current.PageId returns an instance of Nullable<int> which will contain the current page ID, or null (if it's being used in the backoffice).
That's the preferred way to get the current pageId, but no there isn't a way to get the "current page" from LINQ to Umbraco, it's not meant to work like that.
Home home =
(
from homeNode in DigibizDataContext.Homes
where homeNode.Id == UmbracoContext.Current.PageId.Value
select homeNode
).Single();
string s1 = home.PropertyName1;
string s2 = home.PropertyName2;
Can I just use both or do you recommend anything?
Also I've build this generic method:
public TDocType GetCurrentPage<TDocType>()
where TDocType : DocTypeBase, new()
{
TDocType docType =
(
from docTypeNode in DigibizDataContext.DataProvider.LoadTree<TDocType>()
where docTypeNode.Id == UmbracoContext.Current.PageId.Value
select docTypeNode
).Single();
return docType;
}
Now I can get the current values like this:
Home home = GetCurrentPage<Home>();
string s1 = home.PropertyName1;
string s2 = home.PropertyName2;
This works but I don't know if things get slower because of this.
If you want the current page to access properties you should use NodeFactory IMO (well actually I'd say go with <umbraco:Item unless you need to do anything with the property value).
L2U is really good if you want to work with site-wide data or working with hierarchical data.
You're right about the right tool for the right job. It's just that in L2U you can get all the properties strongly-typed and in the NodeFactory you need to use GetProperty which I don't like. If I still want to use L2U on the current page is there a difference in performance?
Ok so LoadTree might be slower, but if I use from homeNode inDigibizDataContext.Homes instead of from docTypeNode inDigibizDataContext.DataProvider.LoadTree<TDocType>() there shouldn't be any performance problems?
I've been using my method to get the current page for a while now and I've run into this bug.
Scenario:
1 I update my documenttype 2 I updated my Linq2Umbraco code 3 I call my GetCurrentPage
This worked before updating the documenttype, but now I get the following exception:
Input string was not in a correct format.
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.FormatException: Input string was not in a correct format.
Source Error:
Line 77: where TDocType : DocTypeBase, new()
Line 78: {
Line 79: TDocType docType =
Line 80: (
Line 81: from docTypeNode in LopitalDataContext.DataProvider.LoadTree<TDocType>()
Source File: C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.BLL\Default\DefaultMethods.cs Line: 79
Stack Trace:
[FormatException: Input string was not in a correct format.]
System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) +9594283
System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) +119
System.String.System.IConvertible.ToInt32(IFormatProvider provider) +46
System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) +385
System.Convert.ChangeType(Object value, Type conversionType) +32
umbraco.Linq.Core.Node.NodeDataProvider.LoadFromXml(XElement xml, T node) +2538
umbraco.Linq.Core.Node.NodeTree`1.GetEnumerator() +670
System.Linq.WhereEnumerableIterator`1.MoveNext() +63
System.Linq.Enumerable.Single(IEnumerable`1 source) +196
Lopital.BLL.Default.DefaultMethods.GetCurrentPage() in C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.BLL\Default\DefaultMethods.cs:79
Lopital.WebApplication.UserControls.MaintenanceContract.Page_Load(Object sender, EventArgs e) in C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.WebApplication\UserControls\MaintenanceContract.ascx.cs:43
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +91
System.Web.UI.Control.LoadRecursive() +74
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207
I got it fixed by unpublishing the page and then publish it again. Somehow after changing the documenttype just publishing the page wasn't enough. Not sure if this is a bug or something. At least it works again :).
Ok the problem is back and this time I didn't even change any documenttypes. I'm not sure what the problem is. It almost looks like its random or something.I think it's related to when the umbraco.config is updated (even if another node is published), but I'm not sure. For now I'll stop using the method until I found a solution for this.
Another question related to this topic. I wanted to use the GetCurrentPage method because I can get all the properties strongly-typed. I thought I read somewhere that in JUNO you can get the properties from a node dynamically. If that's true I don't need this GetCurrentPage method anymore.
Now the exception also happens with other LinqToUmbraco methods so the problem is not related the my GetCurrentPage method. Here is the exception again:
Input string was not in a correct format.
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.FormatException: Input string was not in a correct format.
Source Error:
Line 254: (
Line 255: from maintenanceContractItem in LopitalDataContext.MaintenanceContractItems
Line 256: where maintenanceContractItem.AncestorOrDefault().Language == language.ToString()
Line 257: orderby maintenanceContractItem.SortOrder
Line 258: select maintenanceContractItem
Source File: C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.BLL\Controllers\ArticleGroupController.cs Line: 256
Stack Trace:
[FormatException: Input string was not in a correct format.]
System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) +9594283
System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) +119
System.String.System.IConvertible.ToInt32(IFormatProvider provider) +46
System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) +385
System.Convert.ChangeType(Object value, Type conversionType) +32
umbraco.Linq.Core.Node.NodeDataProvider.LoadFromXml(XElement xml, T node) +2538
umbraco.Linq.Core.Node.d__6.MoveNext() +468
System.Linq.WhereEnumerableIterator`1.MoveNext() +87
System.Linq.d__b1`1.MoveNext() +92
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source, Func`2 predicate) +99
umbraco.Linq.Core.DocTypeBase.AncestorOrDefault(Func`2 func) +382
umbraco.Linq.Core.DocTypeBase.AncestorOrDefault() +176
Lopital.BLL.Controllers.<>c__DisplayClass1f.b__1c(MaintenanceContractItem maintenanceContractItem) in C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.BLL\Controllers\ArticleGroupController.cs:256
System.Linq.WhereEnumerableIterator`1.MoveNext() +141
System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217
System.Linq.d__0.MoveNext() +96
System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +327
System.Linq.Enumerable.ToList(IEnumerable`1 source) +58
Lopital.BLL.Controllers.ArticleGroupController.GetMaintenanceContractItems(Language language) in C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.BLL\Controllers\ArticleGroupController.cs:253
Lopital.Presentation.Layer.ControllerLayer.GetMaintenanceContractItems(Language language) in C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.Presentation\Layer\ControllerLayer.cs:327
Lopital.WebApplication.UserControls.MaintenanceContract.Page_Load(Object sender, EventArgs e) in C:\SVN\lopitalUmbraco\Lopital.Extension\Lopital.WebApplication\UserControls\MaintenanceContract.ascx.cs:46
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +91
System.Web.UI.Control.LoadRecursive() +74
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Control.LoadRecursive() +146
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207
Again it seems like an interger bug, but sometimes it works and sometimes it doens't. Can't find anything which is related to an interger. After publishing all the nodes again (not with republish entire site, but the publish context item on the top node) it now works again. Very strange.
I've put a catch around the parsing method and then rethrown with a new exception that has more information, data trying to be parsed, node ID, node alias and type it's trying to parse.
Linq to Umbraco get single object
Hello,
What is the best way to get a single object in Linq to Umbraco?
Currently this is what I'm doing:
In usercontrols I would like to use the Linq to Umbraco with the current node (yes I've read this). Is there a better way than this:
Jeroen
UmbracoContext.Current.PageId returns an instance of Nullable<int> which will contain the current page ID, or null (if it's being used in the backoffice).
That's the preferred way to get the current pageId, but no there isn't a way to get the "current page" from LINQ to Umbraco, it's not meant to work like that.
Thanks slace!
Is there a big difference in performance between Linq to Umbraco and the NodeFactory?
For example:
Getting properties with the NodeFactory:
Getting the properties with Linq to Umbraco:
Can I just use both or do you recommend anything?
Also I've build this generic method:
Now I can get the current values like this:
This works but I don't know if things get slower because of this.
Jeroen
Right tool for the job is my moto.
If you want the current page to access properties you should use NodeFactory IMO (well actually I'd say go with <umbraco:Item unless you need to do anything with the property value).
L2U is really good if you want to work with site-wide data or working with hierarchical data.
Hi Slace,
You're right about the right tool for the right job. It's just that in L2U you can get all the properties strongly-typed and in the NodeFactory you need to use GetProperty which I don't like. If I still want to use L2U on the current page is there a difference in performance?
Jeroen
I think if you do LoadTree that way you may skip the caching, I'd have to look into the code to check though.
Ok so LoadTree might be slower, but if I use from homeNode in DigibizDataContext.Homes instead of from docTypeNode in DigibizDataContext.DataProvider.LoadTree<TDocType>() there shouldn't be any performance problems?
Jeroen
Looking into the source LoadTree does use the cache so you'll not loose performance.
I've been using my method to get the current page for a while now and I've run into this bug.
Scenario:
1 I update my documenttype
2 I updated my Linq2Umbraco code
3 I call my GetCurrentPage
This worked before updating the documenttype, but now I get the following exception:
Any idea why this is happening?
Jeroen
I'd assume you've added a numerical-based property which isn't in the XML for the page you've loaded up
That's what I also thought in the beginning, but I only added a text field and republished the page so everything should work....
Well it's failing to parse a numeric field, what ever is in the XML is not a valid number, that's all I can really tell you
I got it fixed by unpublishing the page and then publish it again. Somehow after changing the documenttype just publishing the page wasn't enough. Not sure if this is a bug or something. At least it works again :).
Jeroen
Ok the problem is back and this time I didn't even change any documenttypes. I'm not sure what the problem is. It almost looks like its random or something.I think it's related to when the umbraco.config is updated (even if another node is published), but I'm not sure. For now I'll stop using the method until I found a solution for this.
Another question related to this topic. I wanted to use the GetCurrentPage method because I can get all the properties strongly-typed. I thought I read somewhere that in JUNO you can get the properties from a node dynamically. If that's true I don't need this GetCurrentPage method anymore.
Jeroen
Now the exception also happens with other LinqToUmbraco methods so the problem is not related the my GetCurrentPage method. Here is the exception again:
I've put a catch around the parsing method and then rethrown with a new exception that has more information, data trying to be parsed, node ID, node alias and type it's trying to parse.
is working on a reply...