Issue In Generating Business Objects

Apr 16, 2013 at 12:58 PM
I am facing generating the BusinessClasses for my project.

Below is the scenerio

I have three tables in the database

CREATE TABLE [dbo].[business_locations](
[business_location_id] [int] IDENTITY(1,1) NOT NULL,
[business_id] [int] NOT NULL,
[location_name] [varchar](100) NULL,
[location_code] [varchar](50) NULL
CREATE TABLE [dbo].[employee](
[business_employee_id] [int] IDENTITY(1,1) NOT NULL,
[business_id] [int] NULL,
[employee_type] [varchar](30) NULL,
[title] [varchar](20) NULL,
CREATE TABLE [dbo].[employee_location](
[employee_location_id] [int] IDENTITY(1,1) NOT NULL,
[employee_id] [int] NOT NULL,
[location_id] [int] NOT NULL,
Where employee_id in employee_location is foreign key of the table employee and location_id is the foreign key of table business_locations.

Now when I create Business objects I want BusinessLocation and Employee both to have the EmployeeLocationList Collection Property.

But I am unable to do the same. Kindly Suggest how to achieve the CSLAGenFork Tool.

Thanks in Advance,
Developer
Apr 16, 2013 at 3:05 PM
Edited Apr 17, 2013 at 12:34 PM
Select the columns for the child object and use the 'CreateEditable|EditableChild' or 'CreateEditable|EditableChildCollection" gesture. You will then be prompted for the collection and list name as well as the property name in the parent. The new generated classes will then appear in 02.Business Propeties as either 'Child Collection Properties' or 'Non-collection Child Properties'. There is no limit to the number of children.

Image
Apr 16, 2013 at 3:31 PM
Edited Apr 16, 2013 at 3:38 PM
Thanks a lot for the such a quick response.

It's not about having multiple children, my case is about one child in multiple parents.

Let me brief you about my step in next reply.

Kindly suggest.

Thanks,
Apr 16, 2013 at 3:45 PM
I have tried the same and I am getting this error when I am trying to generate the code.

Step 1 ->> I have created Two Editable Root Collection

1) BusinessLocation
2) Employee

Step2 ->> I have created EditableChildCollection with below Properties

Collection Name = EmployeeLocationList
Item Name = EmployeeLocation
Parent Type = Employee
Property Name In Parent Type = EmployeeLocationList.

Till here it is allowing me to generate code.

Error comes when I am doing this

Step 3 -->> I have set the Child Properties of BusinessLocation and did this

Set The Name = EmployeeLocationList

and In Type Name I have selected EmployeeLocationList

After doing this When I am trying to generate the code it is giving the below error.

Object BusinessLocation Child Property EmployeeLocationList Type EmployeeLocationList: Parent Type Employee doesn't match.

Kindly do the needful as I am in dire need of this.

Thanks,
Developer
Apr 16, 2013 at 5:01 PM
unique_902 wrote:
It's not about having multiple children, my case is about one child in multiple parents.
I'm not certain it is possible for a child to have two different parents.
Apr 16, 2013 at 6:42 PM
May be I wrote wrongly.

I am posting the scenario again.

I have tried the same and I am getting this error when I am trying to generate the code.

Step 1 ->> I have created Two Editable Root Collection

1) BusinessLocation
2) Employee

Step2 ->> I have created EmployeeLocationList class as EditableChildCollection with below Properties

Collection Name = EmployeeLocationList
Item Name = EmployeeLocation
Parent Type = Employee
Property Name In Parent Type = EmployeeLocationList.

Till here it is allowing me to generate code.

Error comes when I am doing this

Step 3 -->> I have set the Child Properties of BusinessLocation and did this

Set The Name = EmployeeLocationList

and In Type Name I have selected EmployeeLocationList

After doing this When I am trying to generate the code it is giving the below error.

"Object BusinessLocation Child Property EmployeeLocationList Type EmployeeLocationList: Parent Type Employee doesn't match."

My requirement is I want EmployeeLocationList Property In Employee as well as BusinessLocation Class.

Kindly do the needful as I am in dire need of this.

Thanks,
Apr 16, 2013 at 8:15 PM
Any thought on above message, I am in dire need to solve this issue. Please reply earliest. Don't take my request for early reply in wrong sense.

Thanks,
Coordinator
Apr 17, 2013 at 12:25 AM
Edited Apr 17, 2013 at 1:22 AM
Hi,

I guess your tables should be defined as follows
CREATE TABLE [dbo].[business_locations](
    [business_location_id] [int] IDENTITY(1,1) NOT NULL,
    [business_id] [int] NOT NULL,
    [location_name] [varchar](100) NULL,
    [location_code] [varchar](50) NULL,
 CONSTRAINT [PK_business_locations] PRIMARY KEY CLUSTERED 
(
    [business_location_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[employee](
    [business_employee_id] [int] IDENTITY(1,1) NOT NULL,
    [business_id] [int] NULL,
    [employee_type] [varchar](30) NULL,
    [title] [varchar](20) NULL,
 CONSTRAINT [PK_employee] PRIMARY KEY CLUSTERED 
(
    [business_employee_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[employee_location](
    [employee_location_id] [int] IDENTITY(1,1) NOT NULL,
    [employee_id] [int] NOT NULL,
    [location_id] [int] NOT NULL,
 CONSTRAINT [PK_employee_location] PRIMARY KEY CLUSTERED 
(
    [employee_location_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[employee_location]  WITH CHECK ADD  CONSTRAINT [FK_employee_location_business_locations] FOREIGN KEY([location_id])
REFERENCES [dbo].[business_locations] ([business_location_id])
GO

ALTER TABLE [dbo].[employee_location] CHECK CONSTRAINT [FK_employee_location_business_locations]
GO

ALTER TABLE [dbo].[employee_location]  WITH CHECK ADD  CONSTRAINT [FK_employee_location_employee] FOREIGN KEY([employee_id])
REFERENCES [dbo].[employee] ([business_employee_id])
GO

ALTER TABLE [dbo].[employee_location] CHECK CONSTRAINT [FK_employee_location_employee]
GO
There are two main tables for employees and for locations and a relation table employees_locations. First of all let me say you don't need a PK on employees_locations table; you can delete the employee_location_id column and make a PK composed of both employee_id and business_id.
CslaGenFork can handle it with or without employee_location_id column.

I presume there is a "many to many" relationships, i.e. an employee can be found on many locations and a location can have many employees.

Reviewing your steps
Step 1 ->> I have created Two Editable Root Collection 

1) BusinessLocation 
2) Employee 
Step 1 is ok
Step2 ->> I have created EditableChildCollection with below Properties 

Collection Name = EmployeeLocationList 
Item Name = EmployeeLocation 
Parent Type = Employee 
Property Name In Parent Type = EmployeeLocationList. 
I'm afraid we have to change something around. Let's break down the analysis for each object graph.

First we'll look at locations:
  • EditableRootCollection - BusinessLocationCollection
  • EditableChild - BusinessLocation (item of BusinessLocationCollection- i.e. the parent type)
  • EditableChildCollection - LocationEmployeeCollection (parent type BusinessLocation / child property name Employees)
  • EditableChild - LocationEmployee (item of LocationEmployeeCollection - i.e. the parent type)
Creating an EditableRootCollection is easy. Let's see a picture for the EditableChildCollection.

Image

Like that you have a collection (or list) of employees for each location.

Now lets look at the employees graph:
  • EditableRootCollection - EmployeeCollection
  • EditableChild - Employee (item of EmployeeCollection - i.e. the parent type)
  • EditableChildCollection - EmployeeLocationCollection (parent type Employee / child property name Locations)
  • EditableChild - EmployeeLocation (item of EmployeeLocationCollection - i.e. the parent type)
Let's see the picture for the EditableChildCollection.

Image

So you have a list (or collection) of locations for each employee.

Now a picture for a final note. For the lowest level EditableChild (I mean the items of the child collection), check the parent properties usage

Image

If your relation table doesn't have its own IsIdentity PK - the employee_location_id column - in the the parent property usage you should specify InsertUpdateDelete.

I hope I have correctly interpreted your intentions and I also hope this is clear enough for you. Remember you can't "re-use" a member of an object graph on another object graph. Although both members might look the same, they are in fact different - the parent property is always excluded from the value properties.

The later might seem odd but objects aren't database tables and you don't need (nor should have) a property to know who your object's parent is. CSLA .NET provides a Parent property and when it doesn't, CslaGenFork generates a ParentList. Anyway most of the time you work top to bottom and you just need to know who your chidrens are.

Tiago Freitas Leal
Coordinator
Apr 17, 2013 at 1:18 AM
Edited Apr 17, 2013 at 1:23 AM
RumbleCow wrote:
unique_902 wrote:
It's not about having multiple children, my case is about one child in multiple parents.
I'm not certain it is possible for a child to have two different parents.
Hi Keith,

You are right. A child type can't have two different parent types. You have to name each child type with a unique name. Anyway they have different properties.

Tiago Freitas Leal
Apr 17, 2013 at 4:44 AM
I guess You have understood my problem in correct manner. But what makes me confuse is this say tomorrow we will have third foreign key column in the table EmployeeLocation. So I will have to have again the third ChildCollection Class like you mentioned EmployeeLocation and LocationEmployee.

I have tried the same stuff with CodeSmith and CSLAExtension Code Generator and they are creating the Below property in both BusinessLocation and Employee Classes
            public static PropertyInfo<EmployeeLocationList> employee_locationProperty = RegisterProperty<EmployeeLocationList>(c => c.employee_location);
    public EmployeeLocationList employee_location
    {
        get { return GetProperty<EmployeeLocationList>(employee_locationProperty); }
        private set 
        {
            SetProperty<EmployeeLocationList>(employee_locationProperty, value);            
        }
    }
Please let me know your thought on this.

Thanks,
Apr 17, 2013 at 8:11 AM
Edited Apr 17, 2013 at 8:11 AM
Do let me know if I am doing anything wrong or any other suggestion on my previous post.

Thanks,
Apr 17, 2013 at 6:46 PM
Please reply with some solution as I am pretty much stuck up due to this. Is there any way to solve the above scenario using CSLAGenFork.

Thanks,
Ronak
Coordinator
Apr 17, 2013 at 8:20 PM
unique_902 wrote:
I have tried the same stuff with CodeSmith and CSLAExtension Code Generator and they are creating the Below property in both BusinessLocation and Employee Classes
(...)
Please let me know your thought on this.

Thanks,
Hi Ronak,

As you will understand I won't comment on what other code generators do.

I can say two things:
1) CslaGenFork is made to be used in a specific way, targeting a CSLA .NET programming model. Either you work with the code generator and get the expected results or you work against the code generator and you will get the wrong result, meaning warnings, errors and generation crashes.
2) The CSLA .NET programming model used by CslaGenFork is the ProjectTracker sample you can get at CSLA .NET Project Tracker sample

I believe most of your questions are answered by the referred sample.

Tiago Freitas Leal
Apr 18, 2013 at 4:33 AM
First of all sorry, If I have offended you. I didn't mean anything while I used the reference of other code generators, I specified them because CSLAGenFork is using some of the CodeSmith Templates. I wanted below property to be in both of BusinessLocation and Employee classes, in this your suggestion is having two different classes EmployeeLocation and LocationEmployee.

public static PropertyInfo<EmployeeLocationList> employee_locationProperty = RegisterProperty<EmployeeLocationList>(c => c.employee_location);
public EmployeeLocationList employee_location
{
    get { return GetProperty<EmployeeLocationList>(employee_locationProperty); }
    private set 
    {
        SetProperty<EmployeeLocationList>(employee_locationProperty, value);            
    }
}
Is that something which is possible through some settings in the CSLAGenFork.

Thanks,
Coordinator
Apr 18, 2013 at 6:04 AM
Edited Apr 18, 2013 at 6:05 AM
Hi Ronak,

I wasn't offended at all by your question about "what others do". I just think it's pointless to discuss about something I don't know at all.

Concerning your question, I really don't understand it because it sounds just like your initial question. You asked how to use CslaGenFork to generate a many-to-many relationship. I already answered that question. The answer was clear enough? Did you try it? Was there any problem?

Tiago Freitas Leal
Apr 18, 2013 at 6:43 AM
Edited Apr 18, 2013 at 6:44 AM
Yes I tried there is no point writing here without trying. Why I am repeatedly asking the same question is due to the answer I am not getting clear to me. There is not at all problem in the solution you suggested but My Concern is to have only One Class EmployeeLocation and One Collection EmployeeLocationList.

And EmployeeLocationList will be a property in both Employee and BusinesssLocation.

Let me send you the property details of the both classes here.


BusinessLocation Class Code



namespace Scheduler_CodeGen.Business
{
[Serializable]
[Csla.Server.ObjectFactory(FactoryNames.BusinessLocationFactoryName)]
public partial class BusinessLocation : BusinessBase<BusinessLocation>
{

  private static readonly PropertyInfo<System.Int32> _businessLocationIdProperty = RegisterProperty<System.Int32>(p => p.BusinessLocationId, "Business Location Id");
    [System.ComponentModel.DataObjectField(true, true)]
    public System.Int32 BusinessLocationId
    {
        get { return GetProperty(_businessLocationIdProperty); }
        internal set{ SetProperty(_businessLocationIdProperty, value); }
    }

    private static readonly PropertyInfo<System.Int32> _businessIdProperty = RegisterProperty<System.Int32>(p => p.BusinessId, "Business Id");
    public System.Int32 BusinessId
    {
        get { return GetProperty(_businessIdProperty); }
        set{ SetProperty(_businessIdProperty, value); }
    }

    private static readonly PropertyInfo<System.String> _locationNameProperty = RegisterProperty<System.String>(p => p.LocationName, "Location Name", (System.String)null);
    public System.String LocationName
    {
        get { return GetProperty(_locationNameProperty); }
        set{ SetProperty(_locationNameProperty, value); }
    }
__ // OneToMany
    private static readonly PropertyInfo<EmployeeLocationList> _employeeLocationsProperty = RegisterProperty<EmployeeLocationList>(p => p.EmployeeLocations, Csla.RelationshipTypes.Child);
    public EmployeeLocationList EmployeeLocations__
    {
        get
        {
            bool cancel = false;
            OnChildLoading(_employeeLocationsProperty, ref cancel);

            if (!cancel)
            {
                if(!FieldManager.FieldExists(_employeeLocationsProperty))
                {
                    var criteria = new Scheduler_CodeGen.Business.EmployeeLocationCriteria {LocationId = BusinessLocationId};


                    if(!Scheduler_CodeGen.Business.EmployeeLocationList.Exists(criteria))
                        LoadProperty(_employeeLocationsProperty, Scheduler_CodeGen.Business.EmployeeLocationList.NewList());
                    else
                        LoadProperty(_employeeLocationsProperty, Scheduler_CodeGen.Business.EmployeeLocationList.GetByLocationId(BusinessLocationId));
                }
            }

            return GetProperty(_employeeLocationsProperty);
        }
    }

}
}


Employee Class Code


using System;

using Csla;
using Csla.Data;
using System.Data.SqlClient;

using Csla.Rules;

namespace Scheduler_CodeGen.Business
{
[Serializable]
[Csla.Server.ObjectFactory(FactoryNames.EmployeeFactoryName)]
public partial class Employee : BusinessBase<Employee>
{


    #region Properties

    private static readonly PropertyInfo<System.Int32> _businessEmployeeIdProperty = RegisterProperty<System.Int32>(p => p.BusinessEmployeeId, "Business Employee Id");
    [System.ComponentModel.DataObjectField(true, true)]
    public System.Int32 BusinessEmployeeId
    {
        get { return GetProperty(_businessEmployeeIdProperty); }
        internal set{ SetProperty(_businessEmployeeIdProperty, value); }
    }

    private static readonly PropertyInfo<System.Int32?> _businessIdProperty = RegisterProperty<System.Int32?>(p => p.BusinessId, "Business Id", (System.Int32?)null);
    public System.Int32? BusinessId
    {
        get { return GetProperty(_businessIdProperty); }
        set{ SetProperty(_businessIdProperty, value); }
    }

    private static readonly PropertyInfo<System.String> _employeeTypeProperty = RegisterProperty<System.String>(p => p.EmployeeType, "Employee Type", (System.String)null);
    public System.String EmployeeType
    {
        get { return GetProperty(_employeeTypeProperty); }
        set{ SetProperty(_employeeTypeProperty, value); }
    }


__ // OneToMany
    private static readonly PropertyInfo<EmployeeLocationList> _employeeLocationsProperty = RegisterProperty<EmployeeLocationList>(p => p.EmployeeLocations, Csla.RelationshipTypes.Child);
    public EmployeeLocationList EmployeeLocations__
    {
        get
        {
            bool cancel = false;
            OnChildLoading(_employeeLocationsProperty, ref cancel);

            if (!cancel)
            {
                if(!FieldManager.FieldExists(_employeeLocationsProperty))
                {
                    var criteria = new Scheduler_CodeGen.Business.EmployeeLocationCriteria {EmployeeId = BusinessEmployeeId};


                    if(!Scheduler_CodeGen.Business.EmployeeLocationList.Exists(criteria))
                        LoadProperty(_employeeLocationsProperty, Scheduler_CodeGen.Business.EmployeeLocationList.NewList());
                    else
                        LoadProperty(_employeeLocationsProperty, Scheduler_CodeGen.Business.EmployeeLocationList.GetByEmployeeId(BusinessEmployeeId));
                }
            }

            return GetProperty(_employeeLocationsProperty);
        }
    }

   #endregion

}
}

You had already suggested using the different child collection and that is working but I want something mentioned above.

Please see the code I had highlighted using //One To Manny in both the classes have same collection as property and I am trying for the same using some child collection property settings but some how not able to do it. Is this something possible using the CSLAGenFork.

Thanks,
Ronak
Coordinator
Apr 18, 2013 at 8:36 AM
unique_902 wrote:
Yes I tried there is no point writing here without trying. Why I am repeatedly asking the same question is due to the answer I am not getting clear to me. There is not at all problem in the solution you suggested but My Concern is to have only One Class EmployeeLocation and One Collection EmployeeLocationList.
Hi Ronak,

Please read my previous answers as there is no point in repeating myself.

Tiago Freitas Leal