Relation between ContentItem and Part

Topics: Customizing Orchard
May 25, 2011 at 2:15 AM
Edited May 25, 2011 at 2:20 AM

I'm just new to orchard , i have read some docs about relation and data access , but when i use it in my project , it doesn't work properly . Here is my situation : I want to customize Orchard.User project, I have created 2 parts : CompanyPart and AddressPart , then I created a content type name : Company with these 2 parts . I want to add reference of Company content items to User , so i need to insert some code inside UserPart.cs and UserPartRecord.cs ( Orchard.User project ).

This is UserPart.cs

 

public sealed class UserPart : ContentPart<UserPartRecord>, IUser {
        public const string EmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

        public string UserName {
            get { return Record.UserName; }
            set { Record.UserName = value; }
        }

        public string Email {
            get { return Record.Email; }
            set { Record.Email = value; }
        }

        public string NormalizedUserName {
            get { return Record.NormalizedUserName; }
            set { Record.NormalizedUserName = value; }
        }

        public UserStatus RegistrationStatus {
            get { return Record.RegistrationStatus; }
            set { Record.RegistrationStatus = value; }
        }

        public UserStatus EmailStatus {
            get { return Record.EmailStatus; }
            set { Record.EmailStatus = value; }
        }

        private readonly LazyField<IContent> _company = new LazyField<IContent>();

        public LazyField<IContent> CompanyField { get { return _company; } }

        public IContent Company
        {
            get { return _company.Value; }
            set { _company.Value = value; }
        }
    }


And UserPartRecord.cs

public class UserPartRecord : ContentPartRecord {
        public virtual string UserName { get; set; }
        public virtual string Email { get; set; }
        public virtual string NormalizedUserName { get; set; }

        public virtual string Password { get; set; }
        public virtual MembershipPasswordFormat PasswordFormat { get; set; }
        public virtual string HashAlgorithm { get; set; }
        public virtual string PasswordSalt { get; set; }

        public virtual UserStatus RegistrationStatus { get; set; }
        public virtual UserStatus EmailStatus { get; set; }
        public virtual string EmailChallengeToken { get; set; }

        public virtual ContentItemRecord Company { get; set; }
    }
Migrations.cs
public int UpdateFrom1() {
            SchemaBuilder.AlterTable("UserPartRecord", table => table.AddColumn<int>("Company_Id"));

            return 2;
        }

The User handler file is pretty the same as SponsorHandler in "Creating 1-N and N-N Relations" document

The problem is that when I debug the project , always an error: 
In DefaultContentQuery.cs ( Orchard.ContentManagement) Line 142:
return criteria.List<ContentItemVersionRecord>()
                .Select(x => ContentManager.Get(x.Id, VersionOptions.VersionRecord(x.Id)))
                .ToReadOnlyCollection();

with errors: could not execute query[ SELECT this_.Id as Id54_2_, this_.Number as Number54_2_, this_.Published as Published54_2_,
 this_.Latest as Latest54_2_, this_.Data as Data54_2_, this_.ContentItemRecord_id as ContentI6_54_2_, contentite1_.Id as Id52_0_, 
contentite1_.Data as Data52_0_, contentite1_.ContentType_id as ContentT3_52_0_, userpartre2_.Id as Id41_1_, userpartre2_.UserName as UserName41_1_, 
userpartre2_.Email as Email41_1_, userpartre2_.NormalizedUserName as Normaliz4_41_1_, userpartre2_.Password as Password41_1_, 
userpartre2_.PasswordFormat as Password6_41_1_, userpartre2_.HashAlgorithm as HashAlgo7_41_1_, userpartre2_.PasswordSalt as Password8_41_1_, 
userpartre2_.RegistrationStatus as Registra9_41_1_, userpartre2_.EmailStatus as EmailSt10_41_1_, userpartre2_.EmailChallengeToken as EmailCh11_41_1_, 
userpartre2_.Company_id as Company12_41_1_ FROM hrm_Orchard_Framework_ContentItemVersionRecord this_ inner join 
hrm_Orchard_Framework_ContentItemRecord contentite1_ on this_.ContentItemRecord_id=contentite1_.Id inner join hrm_Orchard_Users_UserPartRecord 
userpartre2_ on contentite1_.Id=userpartre2_.Id WHERE userpartre2_.NormalizedUserName = @p0 and this_.Published = @p1 ]Positional parameters:  
#0>admin #1>True[SQL: SELECT this_.Id as Id54_2_, this_.Number as Number54_2_, this_.Published as Published54_2_, this_.Latest as Latest54_2_, 
this_.Data as Data54_2_, this_.ContentItemRecord_id as ContentI6_54_2_, contentite1_.Id as Id52_0_, contentite1_.Data as Data52_0_, contentite1_.ContentType_id as 
ContentT3_52_0_, userpartre2_.Id as Id41_1_, userpartre2_.UserName as UserName41_1_, userpartre2_.Email as Email41_1_, userpartre2_.NormalizedUserName as 
Normaliz4_41_1_, userpartre2_.Password as Password41_1_, userpartre2_.PasswordFormat as Password6_41_1_, userpartre2_.HashAlgorithm as HashAlgo7_41_1_, 
userpartre2_.PasswordSalt as Password8_41_1_, userpartre2_.RegistrationStatus as Registra9_41_1_, userpartre2_.EmailStatus as EmailSt10_41_1_, 
userpartre2_.EmailChallengeToken as EmailCh11_41_1_, userpartre2_.Company_id as Company12_41_1_ FROM hrm_Orchard_Framework_ContentItemVersionRecord this_ inner join 
hrm_Orchard_Framework_ContentItemRecord contentite1_ on this_.ContentItemRecord_id=contentite1_.Id inner join hrm_Orchard_Users_UserPartRecord userpartre2_ on 
contentite1_.Id=userpartre2_.Id WHERE userpartre2_.NormalizedUserName = @p0 and this_.Published = @p1]

and exception thrown:


Invalid column name 'Company_id'.

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.SqlClient.SqlException: Invalid column name 'Company_id'.

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 

[SqlException (0x80131904): Invalid column name 'Company_id'.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +2030802
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +5009584
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +234
   System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2275
   System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33
   System.Data.SqlClient.SqlDataReader.get_MetaData() +86
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +311
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +987
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
   System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12
   System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader() +12
   NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd) +321
   NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session) +365
   NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +420
   NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) +106
   NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) +172


Any help plzz:(

May 25, 2011 at 12:42 PM

Ok; this isn't why you're seeing the error - but making any changes in Orchard's core modules is a Bad Idea (unless you really really have to). For one thing it'll create a maintenance nightmare if you want to update your Orchard version in the future! And it would make it much harder for you to reuse your work on future projects. So you should try and do everything in a modular fashion.

How you approach this instead is create your own parts to add to the User object. Instead of modifying UserPart, just add your own parts containing whatever fields and functionality you need. Then in the migration just add your new part to the User content type.

As to why that error is happening - it might just be that id needs to be lower case, i.e. Company_id.

Just one final thing to note; I'm working on this module called Mechanics which is designed for creating all kinds of relationships between content items (each relationship is itself defined as a "connector" content item, so you can build pretty much any relationship with it, even defining the multiplicity of both ends all from the admin UI!). I was actually going to publish an example project where addresses and other details could be added to users. So if that sounds of use to you, it's at http://scienceproject.codeplex.com and I'm happy to provide detailed assistance getting to grips with it, since the documentation is still being worked on.

Jun 3, 2011 at 10:44 AM

Thanks i've solved this problem, like u said just leave UserPart as it is