Can't modify m:n relationship

Posts   
 
    
Posts: 10
Joined: 06-Aug-2009
# Posted on: 10-Sep-2009 19:25:38   

I have a shipper table that has a m:n relationship with contact information. This m:n table is essentially made up of three columns:

ShipperId ContactInfoId ContactName

When one of my end users goes in to modify the contact information I am unable to get it to update. I have tried everything that I know of, so I hope someone can help.

So in one particular case my end user chooses contact information that is already found in the database during a CheckForDuplicateContactInfo method. So I tried this first:

duplicateContactInfo = CheckForDuplicateContactInfo(....arguments....);

shipper.ShipperContactInfo[0].ContactInfo = duplicateContactInfo;
shipper.ContactInfo[0] = duplicateContactInfo;

That didn't work, so I tried:

duplicateContactInfo = CheckForDuplicateContactInfo(....arguments....);

shipper.ShipperContactInfo.Clear();
shipper.ContactInfo.Clear();

ShipperContactInfoEntity shipperContactInfo = shipper.ShipperContactInfo.AddNew();

shipperContactInfo.ContactInfoId = duplicateContactInfo.Id;
shipperContactInfo.ContactInfo = duplicateContactInfo;
shipperContactInfo.Shipper = shipper;
shipperContactInfo.ShipperId = shipper.Id;
shipperContactInfo.ContactName = "DEFAULT";

shipper.ContactInfo[0] = duplicateContactInfo;

That didn't work either, so finally I tried:


duplicateContactInfo = CheckForDuplicateContactInfo(....arguments....);

shipper.ShipperContactInfo.DeleteMulti();  //No query executed on the db?!?!

ShipperContactInfoEntity shipperContactInfo = shipper.ShipperContactInfo.AddNew();

shipperContactInfo.ContactInfoId = duplicateContactInfo.Id;
shipperContactInfo.ContactInfo = duplicateContactInfo;
shipperContactInfo.Shipper = shipper;
shipperContactInfo.ShipperId = shipper.Id;
shipperContactInfo.ContactName = "DEFAULT";

shipper.ContactInfo[0] = duplicateContactInfo;

None of these work....I don't understand how I am supposed to update this relationship. I have literally exhausted every method I could come up with to get this relationship to update as needed. Even if the entity is marked dirty and I call save on the entity there is nothing even executed at the db level. This is quite frustrating, please show me where I am going wrong here.

Thanks, Josh

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 10-Sep-2009 21:14:58   

Have you tried


shipper.ContactInfo.Add(duplicateContactInfo)

It's a collection so you need to add entities to it.

Matt

Posts: 10
Joined: 06-Aug-2009
# Posted on: 10-Sep-2009 21:38:04   

MTrinder wrote:

Have you tried


shipper.ContactInfo.Add(duplicateContactInfo)

It's a collection so you need to add entities to it.

Matt

Matt,

Thank you for the response. Yes, I am sorry I have tried that as well. I have removed existing entities from the collection by doing

shipper.ContactInfo.Clear();
shipper.ShipperContactInfo.Clear();

Then I added the entities back that I needed. This also did not work and still "executed" without actually executing a query on the db. I am beginning to believe there is a bug somewhere in here.

Thanks, Josh

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 11-Sep-2009 05:31:34   

Hi Josh, please provide us some relevant info: http://llblgen.com/TinyForum/Messages.aspx?ThreadID=7722

In special: - LLBLGen runtime library version - Code snippet of the Save action (are you saving recursively? and Where the duplicateContactInfo come from (provide code snippet)? - Generated SQL if any.

David Elizondo | LLBLGen Support Team
Posts: 10
Joined: 06-Aug-2009
# Posted on: 11-Sep-2009 15:45:52   

daelmo wrote:

Hi Josh, please provide us some relevant info: http://llblgen.com/TinyForum/Messages.aspx?ThreadID=7722

In special: - LLBLGen runtime library version - Code snippet of the Save action (are you saving recursively? and Where the duplicateContactInfo come from (provide code snippet)? - Generated SQL if any.

Runtime Version: 2.6 Final

Save Action:

I have tried saving different ways. I have just done the following:


carrier.Save(true);

I have also tried saving the contact info separately such as:


public static void AddContactInfoToCarrier(CarrierEntity carrier, int userId)
        {
            try
            {
                carrier.ContactInfo[0].UserAddedId = userId;
                carrier.ContactInfo[0].DateAdded = DateTime.Now;

                carrier.ContactInfo[0].Save();

                carrier.CarrierContactInfo[0].ContactInfoId = carrier.ContactInfo[0].Id;
                carrier.CarrierContactInfo[0].ContactInfo = carrier.ContactInfo[0];

                carrier.CarrierContactInfo[0].Save();
            }
            catch (Exception ex)
            {
                throw;
            }
        }

Duplicate Contact Info Code Snippet:


public static ContactInfoEntity CheckForExistingContactInfo(string areaCode, string phoneNumber, string faxAreaCode, string faxNumber)
        {
            ContactInfoEntity contactInfo = new ContactInfoEntity();

            if (contactInfo.FetchUsingUCAreaCodePhoneNumberFaxAreaCodeFaxNumber(string.IsNullOrEmpty(areaCode) ? null : areaCode,
                                                                            string.IsNullOrEmpty(phoneNumber) ? null : phoneNumber,
                                                                            string.IsNullOrEmpty(faxAreaCode) ? null : faxAreaCode,
                                                                            string.IsNullOrEmpty(faxNumber) ? null : faxNumber))
            {
                return contactInfo.IsNew ? null : contactInfo;
            }

            return null;
        }

As far as generated sql there is none. I added the visualizers as your link recommends and was watching the output and I can see all of the other queries where it is updating the actual carrier table, but it never updates the contactInfo table or the union table that holds the m:n relationship.

Strangely enough I checked to make sure the entities were marked dirty and they are. So I am at a loss.

Thanks, Josh

Posts: 10
Joined: 06-Aug-2009
# Posted on: 11-Sep-2009 21:35:54   

Have I not provided enough information yet? If there is more that I can provide, please let me know.

Thanks, Josh

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 11-Sep-2009 22:42:51   

Hi Josh,

I see a couple of things:

  1. At this code:
shipper.ContactInfo[0] = duplicateContactInfo;

You are modifying the m:n entity and setting the ContactInfo entity. This wont work because m:n collections are read-only. Additionally, if duplicateContactInfo is other contact info than the PK of shippercontactinfo, that would cause problems in the PK/FK syncronization. So, you have to save the m:n relation separately:

...
ShipperContactInfoEntity shipperContactInfo = new ShipperContactInfoEntity();

shippercontactInfo.ContactInfo = duplicateContactInfo;
shippercontactInfo.Shipper = shipper;
shippercontactInfo.ContactName = "DEFAULT";
shippercontactInfo.Save();
...

Please check How I do examples. I quote the docs:

The generated code will not save intermediate table entries in an m:n relation. Consider the two entities Department (DepartmentID (PK, int, identity), Description) and Employee (EmployeeID (PK, int, identity), Name). These two entities have an m:n relation, and this results in the third entity DepartmentEmployees (DepartmentID (PK), EmployeeID (PK)). To relate a new employee with an existing department follow the example below. It will add a new employee to the existing department with ID 1. You can of course also set the DepartmentID of the DepartmentEmployeesEntity by hand, avoiding the necessity to fetch the DepartmentEntity first.

And the code example is:

// C#
DepartmentEntity department = new DepartmentEntity(1);
EmployeeEntity newEmployee = new EmployeeEntity();
newEmployee.Name = "John Doe";
DepartmentEmployeesEntity departmentEmployees = new DepartmentEmployeesEntity();
departmentEmployees.Department = department;
departmentEmployees.Employee = employee;
// save recursively
departmentEmployees.Save(true);

You can start a transaction before all your saves to ensure atomicity.

So, in conclusion the problem is when you modify the m:n entities. To avoid this use the entities (or collection) that represent the m:n collection separately and save them separately. You can save recursively but you need to save via that collection (m:n) instead of your root entity (shipper for example).

  1. In your first code snippet you are using "shipper" but in your last post you are saving "carrier". I lost there.
David Elizondo | LLBLGen Support Team