I have created OData service for a relational table. I am trying to figure out how my post query will look like when posting to tables that has foreign key relation and also to reduce number of calls.
Example tables are:
Person
PersonID
Name
EmailAddress
Residence
ResidenceID
PersonID
Address
In order to create new entry into residence table, typically I will find out the PersonID based on the name or email address and then insert into Residence table.
How can I accomplish the same using my OData JSON api with single call? Is it possible? I am using fiddler to test the service.
Thanks in advance.
-ap
In general, there's not a really good way to do this in OData - but don't stop reading, I'll explain why and provide a few suggestions.
The reason you should think twice about doing this in production is because of the fragility of the insert process. What happens if you have two people in the database with the same name? What if there's nobody with that name? What if you misspelled the name? Would you throw an HTTP error for duplicates? Would they have to retry the insert? <- In essence, there are a ton of questions that arise because the user didn't actually pick a particular record for binding to the new record. This process is greatly simplified if you select the Person up front and just insert the new Residence with a binding to the PersonID. In the new JSON format for OData, that would look something like this:
{
"odata.type": "My.User",
"ReferredBy#odata.bind": "http://.../MyService.svc/Users('haoche')",
"BillingAddress": {
"odata.type": "My.Address",
"City": "Clinton",
"Line1": "23456 Cleveland St",
"Line2": null,
"State": "TX",
"ZipCode": "98052"
},
"DisplayName": "David Hamilton",
"FavoriteTags": [],
"JoinedAt": "2012-10-05T14:14:43.1229977-07:00",
"LastSeenAt": "2012-10-05T14:14:43.1269991-07:00",
"UserID": "davham"
}
That "ReferredBy#odata.bind" is where you put the ID of the person you're linking to. If you're not using the new OData format, the payload would look like this (see example 2). Shameless plug: this is why you should be using the new JSON format :).
So the primary suggestion I have is that I would really, strongly recommend that you have users look up the data first rather than trying to combine two operations into one. If, however, you're really set on having one operation, you could do so with a service operation or an action, depending on what version of OData you're using.
Related
I am attempting to develop an api in go, to allow the user to specify an arbitrary data structure, and easily set up endpoints that perform CRUD operations on an auto generated postgres database, based on the structure that they define.
For now, I have been using gorm, and am able to have a database automatically generated based on a user-defined set of structs, that support all types of relations (has one, one to many, etc.). I am also able to insert into the generated database, when JSON is sent in through the endpoints.
The issue I have discovered, is when I try to receive the data. It seems where many of the go ORMs fall short on, is mapping data from all tables back into the nested structs of the parent struct.
For example, if the user defines:
type Member struct {
ID string
FirstName string
Hometown Hometown `gorm:"ForeignKey:MemberRefer"`
}
type Hometown struct {
ID string
City string
Province string
MemberRefer string
}
The database creates the tables:
Members
id
first_name
Hometowns
id
city
province
member_refer
However, when retrieving the data, all that is mapped back is:
{
"id": "dc2bb591-506f-40a5-a141-bdc0c8410ba1",
"name": "Kevin Krishna",
"hometown": {
"id": "",
"city": "",
"province": ""
}
}
Does anyone know of a go orm that supports this kind of behaviour?
Thanks
5 sec google search showed me the answer:
Preloading associations
Now that you actually have them properly related, you can .Preload() get the nested object you want:
db.Preload("GoogleAccount").First(&user)
Get nested object in structure in gorm
https://www.google.com/search?q=gorm+nested+struct+golang
I have a scenario in DynamoDb, where records have a many-to-many relationship.
In SQL, normally I would create an associative table to seperate the records into one-to-many relationships.
For example:
Stories can have multiple locations
Locations have multiple stories
Here is a sample record:
{
"storyId": "asd239ruefjsp32wf",
"name": "Donut store",
"locations": [
{
"locationId": "asdas23r23",
"name": "New South Whales",
"abbreviation": "NSW"
},
{
"locationId": "sdgkhsdf98",
"name": "Queensland",
"abbreviation": "QLD"
}
]
}
This could possibly be separated into 3 tables:
Stories
storyId
locations
Locations
locationId
StoriesLocations (with a GSI - partitionKey = locationId)
storyLocationId
storyId
locationId
My big issue is, a user can search for stories using more than 1 locationId.
GET /stories?locations=sdgkhsdf98,asdas23r23
Querying the StoriesLocations GSI using each storyId separately doesn't seem like a good solution, especially if I then have to get all the story data afterwords and manage pagination.
There is only 1 country currently, that has 7 locations. So only a handful of locations will ever be searched.
Is there a more efficient way of storing the data? or even querying it?
I have chosen DynamoDB because of it's speed to get going and normally I do frontend development. So setting up a SQL database I have not had much experience with. I will also be using Appsync's real time chat stater, which by default uses DynamoDB.
I think only 1 table and 1 Local secondary index(LSI) ie. Stories and locations as stories' table's Local secondary index(LSI) are needed in your scenario. The Stories table uses storyId as its Hash/partition Key and locations as its Sort/range Key. As for the LSI, you can use locations as the sort key and project any Stories' table's attributes you need in the LSI as you can query against it later. this more info on DyamoDB LSI and sort key
Look here for more details.
Stories
HK storyId
SK locations
name
...
(LSI) storiesLocationsIndex
SK locations
name
...
Hope this helps
Should I use relational database schema (3NF) for designing the data storage for Skygear?
For example, I have to usergroup which contains user, should it be Case A or B below?
A.
User{userId}
Group{groupId, groupName}
Grouping(userId, groupId, role}
B.
Group{userId, groupId, groupName, role}
I think I should be having the following result eventually when passing to the app.
{
"groupName":"Group A",
"groupId":"G123",
"administrator":[
{
"userId":"U123"
},
{
"userId":"U456"
}
],
"creator":{
"userId":"U123"
},
"member":[
]
}
3NF is good for data integrity. Everyone love data integrity, but it may not always the first priority when you design an application.
In the case you provided, I will probably opt for A. B requires update of all Group if groupName is changed.
Beside considering how the data pass to app, try to consider how to update and create too?
When to break 3NF in skygear?
No of user in group.
In 3NF, you will probably use aggregate func. Skygear does not provide it yet, common way it to add an user_count column to group record. And update the number when an user is added/removed.
3NF should be used.
Although skygear does not support table joining. It have a Record Relations Data Type for using a foreign key. (although one level only)
https://docs.skygear.io/guides/cloud-db/data-types/android/
One of the requirements for our REST interface is that each resource be identifiable by unique fields (aside from the primary identifier). The reason for this is that we want to be able to handle bulk importing data - in which case the client can't know the system generated primary identifiers.
This means we have to be able to reference our resources by unique fields. Using a primary key our read requests look like this:
GET example.com/rest/customers/1
and to get orders related to that customer
GET example.com/rest/customers/1/orders
Now, lets assume two fields in customer identify it uniquely, name ("foo") and businessId ("bar"). Given that, I came up with the following URI to get the orders for this customer:
GET example.com/someotherpath/customers/foo,bar/orders
But I don't like that I have a different path to identify that this is a resource being accessed via unique fields. How would you structure the above query in a RESTful way using unique fields instead of the primary key?
Further, an order looks like this:
{
<SNIP>
"orderId" : "42"
"_links": {
"customer": {
"href" : "rest/customers/1"
"key": [ "foo", "bar" ]
}
},
}
Any issues with allowing client to interchangeably specify href OR key when communicating with the interface?
For the first bit, I just wouldn't do it. If a customer has a unique id (and they should), I wouldn't allow end users to specify N other fields that happen to also uniquely identify the customer. It's messy for the user (which field goes first?) and also messy for you on the back end.
For the second bit, the issue is: what happens when they specify both? Which takes precedence? Are they going to remember? Do you want to have to support both? It's generally a good idea to only allow one way to do any particular thing if you can get away with it.
I have a table structure like the following:
Companies Addresses
********* *********
ID ID
AddressID ...
BillingAddressID ...
AddressID and BillingAddressID are foreign keys which are present in the Addresses table. When I generate my model based on this table instead of getting what I would expect to get (the AddressID, BillingAddressID) in the company class. I get the following:
public Addresses Addresses { .. }
public global::System.Data.Objects.DataClasses.EntityReference<Addresses> AddressesReference { .. }
public Addresses Addresses1 { .. }
public global::System.Data.Objects.DataClasses.EntityReference<Addresses> Addresses1Reference { .. }
It seems to be replacing BillingAddress with Addresses1 (not quite sure why that's happening). Also this seems to be common wherever I have a foreign key i.e. instead of the ID I get Table then the TableReference.
I think I can see whats happening i.e. instead of giving me the ID alone, it will be doing a lookup and finding the actual record the ID refers to. However, I am not quite sure what the TableReference field is for....
Can explain this a little better for me?
Thanks in advance.
Relationships are represented as objects in Entity Framework, in the same manner as entities. Even if you are not going to work a lot directly on them, relationship object are first class citizens in EF. EF kreates ObjectStateEntry objects for tracking changes on relationships, just like it does it for entities.
That is why there are two references. First one, AddressesReference is a reference to the relationship object, not the exact entity, and second one Addresses is actual entity.
Peter Chan (link), and Julia Lerman in her book Programming Entity Framework, 1st Edition, say that understanding how relationship works in EF is very important. Also they mention that this is first thing that is confusing developer when they start using EF.
The foreign keys are replaced by a reference to the entity (collection) the foreign key points to.
So to add an address to a company you would do something like:
Address a = new Address();
// ... set variables for address here
currentCompany.Addresses = a;
// or, the other way round (for collections)
a.Companies.Add(currentCompany);
EF uses the table names as the reference point when it builds the model and this is why you see "Addresses" and Addresses1". You can open up the entity model in the GUI format and click on each of the associations. These can be renamed to whatever you like, just click on the reference, view the mapping, ensure it is the one that maps "BillingAddressID" to "BillingAddressID" and rename that reference to "BillingAddress".
Note the current "Addresses" reference may be the one mapping the "BillingAddressID" so you have to check both references.
It would probably be best to change the mapping for "AddressID" to be "Address" instead of "Addresses" if it is a one to one mapping as well.