How to create a new record and get the Id?

Topics: General
Jan 16, 2012 at 10:22 AM

Hi,

I have a repository on which I call the Create method and pass a new record. If I don't instantiate the ContentItemRecord property I get the following exception:

"attempted to assign id from null one-to-one property: ContentItemRecord"

However, I want the db to generate the ID and return it back just like ContentManager.Create (it returns the created item, that's fine).

I don't want to use the ContentManager, because I don't need to create a Content, but just insert a new record in my custom table.

How do I do that?

Thanks.

Jan 16, 2012 at 12:15 PM

Not sure exactly what you're trying to do. If you have an Id property on your record, and define it as a Primary Key, the db will generate an Id. If you have a ContentItemRecord property you're defining a relationship to the ContentItemRecord table, and therefore you need to provide the Id that you are relating to.

Perhaps I could better understand your scenario if you post some code.

Jan 18, 2012 at 8:43 AM

Ok, here is the general idea. I create a custom module to display Project items. In Orchard I only need to display those items, but I also expose a REST API to allow a Silverlight application to insert/update/delete projects. Each user in Orchard has its own set of projects.

What I created so far is:

a ProjectRecord : ContentPartRecord class - I actually don't need it to be a ContentPartRecord, but I don't know how to do the data access otherwise

a ProjectHandler:

    public class ProjectHandler : ContentHandler
    {
        public ProjectHandler( IRepository<ProjectRecord> repository )
        {
            Filters.Add( StorageFilter.For( repository ) );
        }
    }

Then I have a ProjectController which works with a service class to CRUD projects. The service is IDependency and provides methods that work with IRepository<ProjectRecord> for CRUD.

As I said, I really don't need the ProjectRecord to inherit from ContentPartRecord, but this is the only way can then do data access in Orchard. I couldn't find a better way reading through the docs and source code of Orchard.

I don't want to see created Projects as content in the Orchard Dashboard. I just want to store them in the DB.

Hope that clears my case. It would be great if you can suggest a better way to do the data access.

Jan 18, 2012 at 9:04 AM

If it's not a Content Part, then you do data access through IRepository<T>.

If it is a Content Part, then you shouldn't do data access through IRepository<T> (you use IContentManager instead).

So you have things slightly the wrong way round ;)

Jan 18, 2012 at 9:07 AM

Oops :)

Then what Filter should I use in the Handler? In StorageFilter.For<T> T should be a ContentPartRecord.

Jan 18, 2012 at 9:10 AM

Handlers are only for Content Parts. That's why it's called a Content Handler ;)  If you're doing normal data access with an IRepository you don't need a StorageFilter, it Just Works - get hold of the IRepository and you're set. The purpose of the StorageFilter is only to tie a ContentPartRecord to a ContentItemRecord.

Jan 18, 2012 at 9:12 AM

Ok, this is one of those moments when I feel stupid. 

Thanks a lot for your help!

Jan 18, 2012 at 9:51 AM

No problem - it seems to be a common misconception. I think the docs could perhaps be improved in this regard.

Jan 18, 2012 at 3:34 PM

And now back to the initial question - IRepository<T>.Create doesn't return a value. When I create a record which has an identity Id column, how do I get the generated Id?

Jan 18, 2012 at 4:19 PM

For the record - to work with IRepository you need a virtual Id property on the class you are trying to persist. Also, all properties you want to work with should be virtual as well. Part of this is described in this discussion http://orchard.codeplex.com/discussions/243973.

Jan 18, 2012 at 5:46 PM

Yeah, it's one of NHibernate's conventions, it's also covered briefly in Orchard documentation. It's the main thing that always bugged me about NHibernate :)

Coordinator
Jan 19, 2012 at 2:43 AM

The virtual part is not actually a convention: it's necessary for the dynamic proxies to be created by Castle.