How to POST / PATCH for a many-to-many relationship object in Azure Mobile Services?

I followed a Field Engineer sample project from Windows Development Center to maintain a mapping of many-to-many relationships on my model. I was worried about how to insert records into many-to-many relationships.

Take my model as an example:

An organization can have many users .

A user can belong to many organizations .

My model class for User looks like this:

public class User
{
    public User()
    {
        this.Organizations = new HashSet<Organization>();
    }

    public int Id { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public string PasswordSalt { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool Active { get; set; }
    public string Picture { get; set; }
    public string PictureMimeType { get; set; }
    public bool Confirmed { get; set; }
    public string ConfirmationKey { get; set; }

    [JsonIgnore]
    public virtual ICollection<Organization> Organizations { get; set; }
}

      

My UserDTO class:

public class UserDTO : EntityData
{
    public string Email { get; set; }
    public string Password { get; set; }
    public string PasswordSalt { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool Active { get; set; }
    public string Picture { get; set; }
    public string PictureMimeType { get; set; }
    public bool Confirmed { get; set; }
    public string ConfirmationKey { get; set; }

}

      

My Organization class:

public class Organization
{
    public Organization()
    {
        this.Users = new List<User>();
    }

    public string Id { get; set; }
    public string Title { get; set; }
    public string LegalName { get; set; }
    public string TaxReference { get; set; }

    [JsonIgnore]
    public virtual ICollection<User> Users { get; set; }
}

      

My OrganizationDTO class:

public class OrganizationDTO : EntityData
{
    public string Title { get; set; }
    public string LegalName { get; set; }
    public string TaxReference { get; set; }

    public virtual ICollection<UserDTO> Users { get; set; }
}

      

With these classes in mind, I created controller classes, I mapped the DTO and Model classes using AutoMapper like this:

cfg.CreateMap<Organization, OrganizationDTO>()
   .ForMember(organizationDTO => organizationDTO.Id, 
      map => map.MapFrom(organization => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(organization.Id))))
   .ForMember(organizationDTO => organizationDTO.Users, 
      map => map.MapFrom(organization => organization.Users));

 cfg.CreateMap<OrganizationDTO, Organization>()
    .ForMember(organization => organization.Id, 
       map => map.MapFrom(organizationDTO => MySqlFuncs.LongParse(organizationDTO.Id)))
    .ForMember(organization => organization.Users, 
       map => map.Ignore());

      

Using the Fluent API, I have defined the relationship between these two entities using the EntityTypeConfiguration class , for example:

public class UserEntityConfiguration : EntityTypeConfiguration<User>
{
    public UserEntityConfiguration()
    {
        this.Property(u => u.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.HasMany<Organization>(u => u.Organizations).WithMany(o => o.Users).Map(uo =>
        {
            uo.MapLeftKey("UserId");
            uo.MapRightKey("OrganizationId");
            uo.ToTable("OrganizationsUsers");
        });
    }
}

      

I created a TableController class to hanlde UserDTO and OrganizationDTO . I have no problem inserting new users or new organizations, but endpoints from what I know each TableController class allows me to add users or organizations individually.

To create a record in the OrganizationUser table, how can I achieve this?

I thought that a PATCH request should be the way to do it, but is it correct? Do I have to define a TableController for this? How can I open the Insert, Update, Select and Delete elements from this relationship? What would be the JSON to send to endpoints?

EDIT 1

I tried to set PATCH property Users in the organization like this:

url: serviceUrl / tables / Organization / 1

JSON body:

{
  "users": [
    {
      "id": "1"
    }
  ]
}

      

But this gave me an error:

The type of one of the primary key values ​​does not match the type defined in the object. See Inner Exception for details. Parameter name: keyValues

Inner Exception:

The argument types "Edm.Int32" and "Edm.String" are not compatible for this operation. Next to the WHERE predicate, row 1, column 78.

It seems like I need to map the string I am posting to the connection table created with the Fluent API, if I'm not wrong, but how do I map the connection table defined with the Fluent API? Is this the PATCH way to do it? Or is there another way?

+3


source to share


1 answer


I think PATCH should work, but I'm not an expert on automapper.

Another option, if you only have a few users in each organization, is to create views in your backend that represent the concatenated tables. See my posts in this forum thread for an example of how this would work: https://social.msdn.microsoft.com/Forums/azure/en-US/4c056373-d5cf-4ca6-9f00-f152d2b01372/best-practice -for-syncing-related-tables-in-offline-mode? forum = azuremobile . The advantage of this approach is that it really simplifies the customer data model and doesn't need to know anything about foreign keys.



However, the problem is that you could get duplicate users / organizations and take up more space in the customer database. However, due to the way my example sets UpdateAt and version, you will get all updates, for example after changing user data.

+1


source







All Articles