could not resolve property: CupRecord of: Orchard.ContentManagement.Records.Content Item Record

Topics: Customizing Orchard, Troubleshooting, Writing modules
Sep 21, 2013 at 2:29 PM
Dear all,

It's me, the Orchard noob again.

After being able to successfully get my migrations done and underway, I've followed this tutorial (http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-part-10) to write my first back-end module.

However, when going to load the Index Method I'm receiving the error shown in the Subjects.

I guess the Issue is, that the class is not getting loaded. If I enter a break-point within this specific record:
    public class CupRecord : ContentPartRecord
    {
        (e.g. here: ) public virtual string Name { get; set; }
        public virtual string Server { get; set; }
        public virtual Int32 Size { get; set; }
        public virtual DateTime StartDate { get; set; }
        public virtual DateTime SignUpFrom { get; set; }
        public virtual DateTime SignupTo { get; set; }
        public virtual Boolean Active { get; set; }
    }
it's not getting hit. Not even If I do something like:
var ARecord = new CupRecord();
the nested ContentItemRecord property within ARecord is null as well. I've checked my database and there is a table like Orchard_Module_CupRecord so I can't see where I've made the error.

I also dropped the mappings file already, just to be sure.

Any help is welcome.

Thanks.

//SantoDE
Coordinator
Sep 22, 2013 at 2:10 AM
Please explain what you are trying to do and how it doesn't work. Why, for example, do you think ContentItemRecord should have a property called CupRecord? Do you have a stack trace?
Sep 22, 2013 at 11:25 AM
Edited Sep 22, 2013 at 11:32 AM
Okay, let me try to make this more clear:

I'm following this tutorial (http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-part-10) to write my own Orchard Backend Module. Within the Controller of my Adminbackend in the Index Action I'm doing:
var cupQuery = Service.CupService.GetCups().List();
While following this line, I end up in DefaultContentQuery.cs
return criteria
                .List<ContentItemVersionRecord>()
                .Select(x => ContentManager.Get(x.ContentItemRecord.Id, _versionOptions != null && _versionOptions.IsDraftRequired ? _versionOptions : VersionOptions.VersionRecord(x.Id)))
                .ToReadOnlyCollection();
which throws the following exception (NHibernate.QueryException):
could not resolve property: CupRecord of: Orchard.ContentManagement.Records.ContentItemRecord
Here's the stack trace:
   at NHibernate.Persister.Entity.AbstractPropertyMapping.ToType(String propertyName)
   at NHibernate.Persister.Entity.AbstractEntityPersister.ToType(String propertyName)
   at NHibernate.Loader.Criteria.EntityCriteriaInfoProvider.GetType(String relativePath)
   at NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetPathInfo(String path)
   at NHibernate.Loader.Criteria.CriteriaQueryTranslator.CreateCriteriaEntityNameMap()
   at NHibernate.Loader.Criteria.CriteriaQueryTranslator..ctor(ISessionFactoryImplementor factory, CriteriaImpl criteria, String rootEntityName, String rootSQLAlias)
   at NHibernate.Loader.Criteria.CriteriaLoader..ctor(IOuterJoinLoadable persister, ISessionFactoryImplementor factory, CriteriaImpl rootCriteria, String rootEntityName, IDictionary`2 enabledFilters)
   at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results)
   at NHibernate.Impl.CriteriaImpl.List(IList results)
   at NHibernate.Impl.CriteriaImpl.List[T]()
   at Orchard.ContentManagement.DefaultContentQuery.Slice(Int32 skip, Int32 count) in c:\Users\Santo\Documents\Visual Studio 2012\Projects\Projekct\trunk\WebFrontend\source\Orchard\ContentManagement\DefaultContentQuery.cs:line 146
   at Orchard.ContentManagement.DefaultContentQuery.ContentQuery`1.Orchard.ContentManagement.IContentQuery<T>.List() in c:\Users\Santo\Documents\Visual Studio 2012\Projects\Projekt\trunk\WebFrontend\source\Orchard\ContentManagement\DefaultContentQuery.cs:line 191
   at Orchard.Projekt.Controllers.TournamentAdminController.<>c__DisplayClass8.<Index>b__5()
   at Orchard.Projekt.Helpers.ManagedController`4.EnsureValidSessionExecution(Func`1 action)
   at Orchard.Projekt.Controllers.TournamentAdminController.Index(PagerParameters pagerParameters, CupSearchViewModel search)
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass13.<InvokeActionMethodWithFilters>b__10()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass13.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass13.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
Actually, my CupRecord has a base property (I guess cause it's inheriting ContentPartRecord) called ContentItemRecord, which is null as well.

See https://dl.dropboxusercontent.com/u/7025707/contentItemRecord.jpg :)

However, the Constructor of my CupRecord is not getting hit at any time, though I call it directly with
CupRecord = new CupRecord();
before hand.

I assume that the null ContentItemRecord property is the reason why the Exception is getting raised afterwards. But I might be wrong on this one.

Hope it's much clearer now. Thanks for the help so far!

Cheers,
//SantoDe
Coordinator
Sep 22, 2013 at 8:25 PM
What seems clear from the stack trace is that your mappings are not correct. Maybe your migration was bad, I can't know. Also, I think you got the error message in reverse: I don't think "could not resolve property: CupRecord of: Orchard.ContentManagement.Records.ContentItemRecord" means that your CupRecord class doesn't have a ContentItemRecord property, but rather that the ContentItemRecord class doesn't have a property called CupRecord. Why it thinks it needs one is anyone's guess. There isn't enough code here to guess.

Also, that criteria query has a horrible Select N+1 problem (or potentially worse) in it. It's going to bring down performance dramatically.
Sep 22, 2013 at 10:30 PM
BertrandLeRoy wrote:
What seems clear from the stack trace is that your mappings are not correct. Maybe your migration was bad, I can't know. Also, I think you got the error message in reverse: I don't think "could not resolve property: CupRecord of: Orchard.ContentManagement.Records.ContentItemRecord" means that your CupRecord class doesn't have a ContentItemRecord property, but rather that the ContentItemRecord class doesn't have a property called CupRecord. Why it thinks it needs one is anyone's guess. There isn't enough code here to guess.

Also, that criteria query has a horrible Select N+1 problem (or potentially worse) in it. It's going to bring down performance dramatically.
Oh, okay. You can see the example code within the tutorial linked above. I followed it, mostly.

I allready deleted the mappings file in order to get it re-generated, just to be sure. Here are my migrations:
using System;
using System.Collections.Generic;
using System.Data;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;

namespace Orchard.Projekt{
    public class Migrations : DataMigrationImpl {

        public int Create() {
            // Creating table Cups
            SchemaBuilder.CreateTable("CupRecord", table => table
                .ContentPartRecord()
                .Column("Name", DbType.String)
                .Column("Server", DbType.String)
                .Column("Size", DbType.Int32)
                .Column("StartDate", DbType.DateTime)
                .Column("SignupFrom", DbType.DateTime)
                .Column("SignupTo", DbType.DateTime)
                .Column("Active", DbType.Boolean)
            );

            // Creating table CupRound
            SchemaBuilder.CreateTable("CupRoundRecord", table => table
                .ContentPartRecord()
                .Column("Cup_Id", DbType.Int32)
                .Column("Number", DbType.Int32)
            );

            // Creating table CupContestant
            SchemaBuilder.CreateTable("CupContestantRecord", table => table
                .ContentPartRecord()
                .Column("CharName", DbType.String)
                .Column("AccountName", DbType.String)
                .Column("Cup_Id", DbType.Int32)
                .Column("Seeding", DbType.Int32)
                .Column("SignUpDate", DbType.DateTime)
            );

            // Creating table CupPairing
            SchemaBuilder.CreateTable("CupPairingRecord", table => table
                .ContentPartRecord()
                .Column("CupRound_Id", DbType.Int32)
                .Column("CupPairing_Id", DbType.Int32)
                .Column("UpperCupContestant_Id", DbType.Int32)
                .Column("LowerCupContestant_Id", DbType.Int32)
                .Column("WinnerCupContestant_Id", DbType.Int32)
                .Column("UpperSeeding", DbType.Int32)
                .Column("LowerSeeding", DbType.Int32)

            );

            return 1;
        }
    }
}
Is it a bit more clear now? Thanks for all your help!
Coordinator
Sep 22, 2013 at 10:53 PM
Edited Sep 22, 2013 at 10:54 PM
Right, I saw the link to the tutorial, but it's very long, so it's better if you provide the relevant bits. Also, I made a search for "cup" on it and it came up empty. So did ".select", so it's hard to tell how you stuck to the tutorial. Even if you did, that doesn't help much, as I haven't written it and don't know its details.

One difference I see between your migration and your class is on the "SignUpFrom" property, which is "SignupFrom" in the migration. Notice the casing of the 'u'.
Developer
Sep 23, 2013 at 1:50 AM
Edited Sep 23, 2013 at 1:58 AM
There is something wrong in the code you use to create/update/query these records - please show us this piece.
Record itself and the mappings look fine (although it's highly likely that you don't need that many content parts).

SantoDE wrote:
However, the Constructor of my CupRecord is not getting hit at any time, though I call it directly with
CupRecord = new CupRecord();
before hand.
Why are you creating the record manually? You're not supposed to do that. CupRecord is a backing record for a content part and content manager handles it's creation and updating (IContentManager.Create(<type name>)).
Coordinator
Sep 23, 2013 at 2:07 AM
Yes: CupRecord is nothing more than a blueprint for nHibernate to build a dynamic proxy with. It will never be instantiated under normal circumstances.
Sep 23, 2013 at 9:27 AM
Thanks for the help so far! I really appreciate it.

pszmyd wrote:
Record itself and the mappings look fine (although it's highly likely that you don't need that many content parts).
What do you mean by that? Why I shouldn't need them.

Ok, I thought It might be a easier to follow the tutorial code. Sorry for that :)

Here's the code I use to read the records:

Controller
var cupQuery = Service.CupService.GetCups().List();
ICupService
    public interface ICupService
    {
        IContentQuery<CupPart> GetCups();
    }
CupService
        public IContentQuery<CupPart> GetCups()
        {
            return _controller.OrchardServices.ContentManager.Query<CupPart, CupRecord>();
        }
That's the Code I've wrote, afterwards it's down to Orchard.Code.

Thanks for enlighten me about the Records and it's blueprint function. This really helps a lot :)
Developer
Sep 23, 2013 at 2:20 PM
Edited Sep 23, 2013 at 2:21 PM
SantoDE wrote:
What do you mean by that? Why I shouldn't need them.
Not that you shouldn't - it always depends on context/scenario. You should wrap up into "content" items what actually makes sense to be a "content".
In other words - if it makes sense for thing X to live on its own, be extended etc. - then it's ok to make it a content item. Take Page, Widget or User for example.
Here's the code I use to read the records:
Still it's a bit unclear. I guess the problem may originate from the way you create those items. Please provide the code that creates those "Cup" items.
Coordinator
Sep 23, 2013 at 4:38 PM
Well, I highlighted a discrepancy between the migration and property naming above. Did you try to fix that?
Sep 23, 2013 at 6:50 PM
Yes, I tried. I fixed it. regenerated the mappings file but I still have the same error.

However, I'm currently not creating those items by myself. Nor do I know how to. I checked my tutorials and I can't see any mention of it in it. Can you reach me a helping hand? I'm feeling like a dumb ass , but I just can't find the cause of the error.
Coordinator
Sep 23, 2013 at 6:54 PM
Well, those are content part records, so they absolutely need an associated content item in order to function at all. So you never create one of those records. Instead you create content items of a type that has the part.
Sep 23, 2013 at 8:04 PM
Okay, and now the final question is : how? How do I create a item that has the part? And the question is where? I thought I just qry the data trough the records (as shown above) and then I'm able to display them.

According to the Orchard Tutorial (http://docs.orchardproject.net/Documentation/Understanding-data-access) thos are created automatically by inheritating ContentPartRecord which I'm doing:
using System;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
using System.ComponentModel.DataAnnotations;

namespace Orchard.Projekt.Model
{
    public class CupRecord : ContentPartRecord
    {
Typically, the record class resides in a folder named Models. The parent class, ContentPartRecord, also includes a property named id and a reference to the content item object. Therefore, an instance of the MapRecord class includes not just Latitude and Longitude but also the id property and the content item object that is used to maintain the relationships between the part and other content.
According to the docs, this should work? Sorry :/
Developer
Sep 23, 2013 at 10:26 PM
Edited Sep 24, 2013 at 1:22 PM
Content parts need to be attached to some content type prior to usage, either
  • via migrations (using ContentDefinitionManager.AlterTypeDefinition - you can find an abundancy of examples in Orchard) or
  • through Dashboard (Content Definition in Orchard 1.7). Parts are just building blocks - not something you can use alone.
Then and only then you can create new items using Services.ContentManager.Create("YourTypeName"). And only after creating items this way, you'll be able to query them.

I guess you missed this documentation topic about content parts: http://docs.orchardproject.net/Documentation/Writing-a-content-part ;)

For simple data storage, without all the overhead and complexity related to using content types etc. you can use the lower-level approach - IRepository<T> on your record class. But this is another story.
Sep 24, 2013 at 8:15 AM
Edited Sep 24, 2013 at 12:09 PM
I can't find the SchemaBuilder.AlterTypeDefinition you've mentioned. What I've found is (and what I already tried):
            ContentDefinitionManager.AlterPartDefinition(
                typeof(CupPart).Name, cfg => cfg.Attachable());
but this doesn't do the trick either. What am I missing?

Additionally, before querying the data I added the following line:
ContentManager.Create("CupRecord");
but it doesn't help as well.

I've checked the documentation you've provided as well, but I can't see any major differences. I also created handlers & drivers, but they are not of any use till now. I got the problem earlier.

I guess I'm lacking a minor thingy, with a major outcome...
Sep 24, 2013 at 12:09 PM
I just figured, that I'm using version 1.6. Should I consider upgrading first?

While I would appreciate to finish this first, and upgrade afterwards.
Developer
Sep 24, 2013 at 1:32 PM
SantoDE wrote:
I can't find the SchemaBuilder.AlterTypeDefinition you've mentioned. (...)
It's an extension method - just search for it. It's used in hunderds of places all around Orchard core. In 1.7 it's in namespace Orchard.ContentManagement.MetaData.

If you haven't used this I'm afraid you haven't created a content type yet, so calling ContentManager.Create("CupRecord"); won't do anything. A content type needs to exist first, then you attach a part to it and then you can create an instance of the type (with all parts in it) using content manager.

Like I wrote before - part is just a building block. Content type is composed using various parts - you declare that in migrations.
Content item is an instance of a given content type, not part alone. It contains instances of previously declared parts in it, which you can access using .As<MyContentPart>() extension method.
Sep 24, 2013 at 1:39 PM
As already mentioned, currently I'm on 1.6. Should I consider upgrading first, or should it work with 1.6 as well?
Coordinator
Sep 24, 2013 at 4:27 PM
No, this API has been there forever, no need to upgrade just for that. Just add a using directive so that you can use the extension method.
Sep 24, 2013 at 7:59 PM
Edited Sep 24, 2013 at 10:07 PM
Okay, now I'm really confused.

Within the last answers somewhen you brought up:
SchemaBuilder.AlterTypeDefinition
but If I look trough the discussion here again, I can only find:
via migrations (using ContentDefinitionManager.AlterTypeDefinition - you can find an abundancy of examples in Orchard)
which is exactly what I'm doing already. I also searched trough orchard core for AlterTypeDefinition and within 1.6, I can only find the ContentDefinitionManager.AlterTypeDefinition we've mentioned a couple of times.

As you can see within one of my posts, I'm using it already. I also double checked Orchard.Core and e.g. it's migration. I can't see any discrepancy between my migration and theres. I'm really clueless and also sorry for acting stupid.

I really appreciate that both of you're trying to help me. I can understand with the ContentItems but while going again trough the documentation, my code should have created it, already.

Additionally, what I was able to figure out:

My migration creates contentParts , I can find them via the admin backend in /Admin/ContentTypes

However, I do not have a ContentType. Shouldn't my migration create this as well? Is this the error?

Edit

I've created a contentType via Baackend and attached parts to it - still not working though
Coordinator
Sep 24, 2013 at 11:14 PM
If you're using it already then great. Note that AlterTypeDefinition is creating the type if it doesn't already exist.

The point is that you cannot create a disembodied part. You need a content item.

When you say something like "still not working" you need to explain how it does not work, we can't just guess.
Sep 24, 2013 at 11:27 PM
Edited Sep 24, 2013 at 11:27 PM
I still get the error mentioned above "Cannot Resolve...".

As you can see, creating the content types and stuff worked. But I just can't create the content item record to query it :/ Or I just dont get how...
Coordinator
Sep 25, 2013 at 12:56 AM
You mean "could not resolve property: CupRecord of: Orchard.ContentManagement.Records.ContentItemRecord" on this line of code: return criteria.List<ContentItemVersionRecord>()?
Developer
Sep 25, 2013 at 2:31 AM
Edited Sep 25, 2013 at 2:33 AM
SantoDE wrote:
(...) but If I look trough the discussion here again, I can only find:
via migrations (using ContentDefinitionManager.AlterTypeDefinition - you can find an abundancy of examples in Orchard)
which is exactly what I'm doing already. I also searched trough orchard core for AlterTypeDefinition and within 1.6, I can only find the ContentDefinitionManager.AlterTypeDefinition we've mentioned a couple of times.

As you can see within one of my posts, I'm using it already. I also double checked Orchard.Core and e.g. it's migration. I can't see any discrepancy between my migration and theres. I'm really clueless and also sorry for acting stupid.
I cannot see any usage of AlterTypeDefinition in the code you provided above (btw - as you already pointed out it's in ContentDefinitionManager, not SchemaBuilder - I corrected my typo above). You only define parts via AlterPartDefinition as far as I can tell. Could you please paste in the whole migrations or better paste a link to download your module so we could see the whole picture?
However, I do not have a ContentType. Shouldn't my migration create this as well? Is this the error?
It's not needed, unless you already have some type to attach your parts to via Dashboard.

We got a bit far from the actual error one may think, but the thing is - there is something wrong either in the mappings or in the way you create/query items. This error basically means that NHibernate cannot resolve your record mapping for some reason when building a query for content items. Are your record classes inside Models folder, btw?
If you could provide full source, like I asked above, we'd be able to tell you what's wrong there.
Sep 25, 2013 at 7:28 AM
It's fixed....

psmyd you're my here. The folder was called Model not Models.

I've just renamed the folder and everything is working. Really, thank you so much. I owe you.
Developer
Sep 26, 2013 at 3:03 AM
Edited Sep 26, 2013 at 3:04 AM
No problem - glad you made it work!
When problems happen it's usually all about those little things;)