How to add new Entity and related n:m relations

Posts   
 
    
varalonga
User
Posts: 7
Joined: 28-Nov-2005
# Posted on: 28-May-2012 22:08:14   

Hi!

I'm sorry to bother you with might be for sure a basic question but I'm kinda of freaking out. Consider the following scenario:

I have a table Employee, that relates to the table Features by an N:M relationship through the table Employee_Features

I want to create a new Employee and add also the according Employee_Features entries, but I'm not achieving it. This is my code.

ctx.StartTransaction(); try { var employee = new EmployeeEntity { IsNew = true };

        employeeFeatures.ForEach(featureId =>
            employee.EmployeeFeatures.Add(
                new EmployeeFeaturesEntity { FeatureId = featureId, IsNew = true }
            )
        );

ctx.Commit(); } catch(Exception ex) { ctx.Rollback(); throw; }

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 29-May-2012 05:42:04   

What is ctx? I presume it's a DataAccessAdapter. You started a transaction but you are not saving anything. You need to save employee explicitly, in fact if you save it recursively (which will save all the related Employee features as well) you don't need to use a transaction, as a recursive save instantiate a transaction inside. Use a transaction if there is more than one .Save action you want to keep together.

So, do something like:

ctx.StartTransaction();
try
{
            var employee = new EmployeeEntity { IsNew = true };
            
            employeeFeatures.ForEach(featureId =>
                employee.EmployeeFeatures.Add(
                    new EmployeeFeaturesEntity { FeatureId = featureId, IsNew = true }
                )
            );

            ctx.SaveEntity(employee, true, true);

ctx.Commit();
}
catch(Exception ex)
{
ctx.Rollback();
throw;
}

or...

ctx = new DataAccessAdapter
try
{
            var employee = new EmployeeEntity { IsNew = true };
            
            employeeFeatures.ForEach(featureId =>
                employee.EmployeeFeatures.Add(
                    new EmployeeFeaturesEntity { FeatureId = featureId, IsNew = true }
                )
            );

            ctx.SaveEntity(employee, true, true);
}
catch(Exception ex)
{
throw;
}
David Elizondo | LLBLGen Support Team
varalonga
User
Posts: 7
Joined: 28-Nov-2005
# Posted on: 29-May-2012 12:49:21   

Hi!

First of all thanks for your quick feedback. You were right about the missing save, but it was saving I just paste my code incorrectly to the message. I tried your code, but I must be missing something since I got the following error:

Cannot insert the value NULL into column 'EmployeeId', table 'CompanyManager.dbo.EmployeeFeatures'; column does not allow nulls. INSERT fails. The statement has been terminated.

The table EmployeeFeatures relates Employees with Features by a double primary key composed by EmployeeId and FeatureId which are, respectively, foreign keys to the tables Employee and Feature. When I do:

new EmployeeFeaturesEntity { FeatureId = featureId, IsNew = true }

I am not stating the EmployeedId, but then again I don't even know it, since this is a brand new Entity; but still I thought this would be filled internal and automatically. What am I doing wrong? Thanks in advance.

kind regards,

Vitor Varalonga

daelmo wrote:

What is ctx? I presume it's a DataAccessAdapter. You started a transaction but you are not saving anything. You need to save employee explicitly, in fact if you save it recursively (which will save all the related Employee features as well) you don't need to use a transaction, as a recursive save instantiate a transaction inside. Use a transaction if there is more than one .Save action you want to keep together.

So, do something like:

ctx.StartTransaction();
try
{
            var employee = new EmployeeEntity { IsNew = true };
            
            employeeFeatures.ForEach(featureId =>
                employee.EmployeeFeatures.Add(
                    new EmployeeFeaturesEntity { FeatureId = featureId, IsNew = true }
                )
            );

            ctx.SaveEntity(employee, true, true);

ctx.Commit();
}
catch(Exception ex)
{
ctx.Rollback();
throw;
}

or...

ctx = new DataAccessAdapter
try
{
            var employee = new EmployeeEntity { IsNew = true };
            
            employeeFeatures.ForEach(featureId =>
                employee.EmployeeFeatures.Add(
                    new EmployeeFeaturesEntity { FeatureId = featureId, IsNew = true }
                )
            );

            ctx.SaveEntity(employee, true, true);
}
catch(Exception ex)
{
throw;
}
Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 29-May-2012 20:25:16   

Would you please confirmthe below points:

  • EmployeeID is the PK of the table Employee
  • EmployeeID is a Sequence/Identity, and is recognized by the Designer as such
  • In the table EmployeeFeature, EmployeeID is a FK

In your code, I don't see any field being set for the employee entity, this way the employee entity will not be saved, in the first place.

And therefore no EmployeeID will be available when saving the EmployeeFeature entities.

Btw: you don't need to set IsNew = true, it is true by default.

varalonga
User
Posts: 7
Joined: 28-Nov-2005
# Posted on: 30-May-2012 03:32:40   

Hi!

Yes... you're right... I forgot to set the fields... As soons as I did it, it began to work. Dummy head of mine... I guess I must take a break... simple_smile Thx a lot!

kind regards,

VĂ­tor Varalonga

Walaa wrote:

Would you please confirmthe below points:

  • EmployeeID is the PK of the table Employee
  • EmployeeID is a Sequence/Identity, and is recognized by the Designer as such
  • In the table EmployeeFeature, EmployeeID is a FK

In your code, I don't see any field being set for the employee entity, this way the employee entity will not be saved, in the first place.

And therefore no EmployeeID will be available when saving the EmployeeFeature entities.

Btw: you don't need to set IsNew = true, it is true by default.