0

Hello I am trying to get relational data using entity frame work from an Azure mobile App.

The info in this tutorial talks a lot about formatting but not about relationships. This one Has related data using entity framework but nothing about azure mobile apps. In this case they use ASP.net Core. How can I put the information from the two together?

I attempted to set up relationships in a similar manner however it does not acknowledge the relationships at all. Does anybody know what to do?

Update Following advice I managed to get the foreign keys to show in the migration so.

The entity definitions are as follows

public class Member : EntityData
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public virtual ICollection<Subscription> Subscriptions { get; set; }


}

public class Subscription : EntityData
{
    public string MemberId { get; set; }
    public string ShopItemId { get; set; }
    public virtual Member Member { get; set; }
    public virtual ShopItem ShopItem { get; set; }
    public int Quantity { get; set; }
}
public class ShopItem : EntityData
{
    public decimal Price { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string Note { get; set; }
}

I suspect that I do not need the virtual properties but I'll leave them in since they are there on the client side.

The migration shows the correct relationship in terms of foreign keys

CreateTable(
            "dbo.Subscriptions",
            c => new
                {
                    Id = c.String(nullable: false, maxLength: 128,
                        annotations: new Dictionary<string, AnnotationValues>
                        {
                            { 
                                "ServiceTableColumn",
                                new AnnotationValues(oldValue: null, newValue: "Id")
                            },
                        }),
                    MemberId = c.String(maxLength: 128),
                    ShopItemId = c.String(maxLength: 128),
                    Quantity = c.Int(nullable: false),
                    Version = c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion",
                        annotations: new Dictionary<string, AnnotationValues>
                        {
                            { 
                                "ServiceTableColumn",
                                new AnnotationValues(oldValue: null, newValue: "Version")
                            },
                        }),
                    CreatedAt = c.DateTimeOffset(nullable: false, precision: 7,
                        annotations: new Dictionary<string, AnnotationValues>
                        {
                            { 
                                "ServiceTableColumn",
                                new AnnotationValues(oldValue: null, newValue: "CreatedAt")
                            },
                        }),
                    UpdatedAt = c.DateTimeOffset(precision: 7,
                        annotations: new Dictionary<string, AnnotationValues>
                        {
                            { 
                                "ServiceTableColumn",
                                new AnnotationValues(oldValue: null, newValue: "UpdatedAt")
                            },
                        }),
                    Deleted = c.Boolean(nullable: false,
                        annotations: new Dictionary<string, AnnotationValues>
                        {
                            { 
                                "ServiceTableColumn",
                                new AnnotationValues(oldValue: null, newValue: "Deleted")
                            },
                        }),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Members", t => t.MemberId)
            .ForeignKey("dbo.ShopItems", t => t.ShopItemId)
            .Index(t => t.MemberId)
            .Index(t => t.ShopItemId)
            .Index(t => t.CreatedAt, clustered: true);

However when making a request to the table api the result is still

{"deleted":false,"updatedAt":"2016-12-07T21:55:19.174Z","createdAt":"2016-12-07T21:55:19.128Z","version":"AAAAAAAAB/s=","id":"1","quantity":1,"shopItemId":"1","memberId":"1"}

which does not include the related entity.

xerotolerant
  • 1,955
  • 4
  • 21
  • 39

1 Answers1

1

I'm new at this too, but I just discovered that it seems to detect relationships automatically if you name your fields appropriately.

Item Table
_______
Id
PersonId

Person Table
____________
Id
FirstName
LastName

In this case here, PersonId in the Item table would match Id in the Person Table.

I am very new to this, so I could be way off, but this is my understanding of it so far.

Just set it up in your model and look at the migration file and see if it picked it up. You'll be able to tell by looking at the code in the migration file.

Update:

Here it is is code. I have not dealt with lazy loading, so I'm not sure how to do that.

class Item
{
  string Id { get; set; }
  string PersonId { get; set; } // This matches Person class Id property
}

class Person
{
  string Id { get; set; }
  string FirstName { get; set; }
  string LastName { get; set; }
}

Another Update:

I just figured out how foreign keys work.

public class GameObject : EntityData
{
    public string PlayerId { get; set; }
    public virtual Player player { get; set; }
}

 public class Player : EntityData
 {
    public string FirstName { get; set; }
    public string LastName { get; set; }
 }

The virtual property tells it that it's a foreign key. Without it, you won't see

.ForeignKey("dbo.Players", t => t.PlayerId)

in your migration when it's created.

In addition, to retrieve the related data, you have to follow the steps listed here: (blogs.msdn.microsoft.com/azuremobile/2014/05/27/

Kenny
  • 2,150
  • 2
  • 22
  • 30
  • Hey. From what i understand that should work and that is what I did. Two things though,could you write the answer to show actual code please? Just to make sure I'm not missing something. Also how does that account for lazy loading, eager loading etc. From what i read you had to handle that yourself. – xerotolerant Dec 07 '16 at 19:47
  • Also I checked my migrations file and there really isn't anything in there for some reason. My database has data and my seed method works fine however my initialCreate migration file is empty save for the class with empty up and down methods. – xerotolerant Dec 07 '16 at 19:51
  • Your initial migration file should not be empty. The commands I used were 1: enable-migrations 2: add-migration initial (This created the first migration based on my models) – Kenny Dec 07 '16 at 21:46
  • If you ran the initial migration before you had models, that might explain why it is blank. – Kenny Dec 07 '16 at 21:47
  • I jacked up my migrations by using `-Ignore changes`. I reworked it and now I have foreign keys showing up as one would expect. But the request now is still returning JSON data without the related entity data. I'll update the question with the progress. – xerotolerant Dec 07 '16 at 22:14
  • Cool. Glad you're figuring it out. :-) – Kenny Dec 07 '16 at 22:15
  • Thanks. I updated the Question now. It seems like I would have to do the loading of the related entities in the tableapi controller however there is no `Include` method on the context in there so I can't just say `Query().Include(c => c.member)` Like they did in the tutorial. – xerotolerant Dec 07 '16 at 22:24
  • See if this helps. I just stumbled upon it. https://msdn.microsoft.com/en-us/library/dd456846(v=vs.100).aspx – Kenny Dec 08 '16 at 01:52
  • This might help too. It explains the concepts involved. https://msdn.microsoft.com/en-us/library/bb896272(v=vs.110).aspx I'm learning all this too. :-) – Kenny Dec 08 '16 at 01:55
  • I just added more info on foreign keys to my answer - just in case it will help someone else who is also drinking from this firehose. – Kenny Dec 08 '16 at 15:55
  • Hey I think I've made some progress, though I have not solved it. [This post](http://stackoverflow.com/questions/23316910/azure-mobile-services-c-sharp-wont-return-child-entities) seems to have the solution in it somewhere. When I change my query to `context.Members.Include("Subscription")` it fails saying that no foreign key exists with that name. `"Subscription"` throws no error which makes me think it is right however the related data is not returned which makes me thing my data objects are improperly formed. Some progress is better than none right? – xerotolerant Dec 11 '16 at 03:00
  • Finally found the solution. Just letting you know. In addition to the steps you mentioned you have to follow the steps [here](https://blogs.msdn.microsoft.com/azuremobile/2014/05/27/retrieving-data-from-1n-relationship-using-net-backend-azure-mobile-services/ since the table controller does not support expand in any way. Once you follow these steps it works. If you update your answer to include it I'll make it correct. – xerotolerant Dec 12 '16 at 17:11
  • Ok - I'm not sure if you were just saying I should update my answer to include the link you gave in your comment, but that's what I did. I briefly reviewed it, and I don't quite get the idea yet, but my mind is focused on another project right now. I will need this info very soon though, so I thank you for finding it. I will certainly update my answer again to explain it better once i wrap my head around the concept. Great team work! – Kenny Dec 12 '16 at 20:29