2

I'm working with Visual Studio 2012 and developing on C#. I just started started working a WCF web service, I created the database through the Model First approach and so far I've been able to insert, update, delete and get entries into simple tables, but I've come across a problem: I don't know how to send the parameters for a table that has a relationship with another table.

To explain better my doubt here's an example: I have a Regions table, then I have this other table called Clusters, a region has many clusters and a cluster belongs to a region.

The resulting classes created by EF look like this:

public partial class Regions
{
    public Regions()
    {
        this.Clusters = new HashSet<Clusters>();
    }

    public int RegionId { get; set; }
    public string Name { get; set; }
    public string Point { get; set; }
    public System.DateTime CreatedDateTime { get; set; }
    public System.DateTime UpdatedDateTime { get; set; }

    public virtual ICollection<Clusters> Clusters { get; set; }
}

public partial class Clusters
{

    public int ClusterId { get; set; }
    public System.DateTime CreatedDateTime { get; set; }
    public System.DateTime UpdatedDateTime { get; set; }

    public virtual Regions Region { get; set; }
}

With this kind of relationship, how can I add a new Cluster? My endpoint for adding a new Cluster receives a string which is a JSON string, I deserialize it into a Cluster object. I deserialize like this:

 Clusters cluster = new JavaScriptSerializer().Deserialize<Clusters>(data); //data is the JSON string

In this case, the only information I'll be sending into the JSON string will be the Region to which the Cluster belongs to (the DateTime for when it is created the object is being added on the server side), but how do I send the Region information into the JSON so it can be added into the Cluster?

What I mean is, do I have to send a JSON string that looks like this?

{"RegionId":2}

Because if I do that, no entry is made, do I have to something else?

I'm really new to working with EF and WCF web services, any help will be appreciated.

Uriel Arvizu
  • 1,876
  • 6
  • 37
  • 97
  • Your Clusters entity does not seem to have a foreign key to the Region. Is it intentional? I believe that without the foreign key you would have to use $links to update relationships. If you have the foreign key you should be able just to update the entity and set the foreign key property accordingly. – Pawel Jan 09 '13 at 00:17
  • I created the database from a model, and I added Navigation Properties to relate both tables, I don't know if those are the foreign keys or how should I create them, I'm new to using Entity Framework Model-First approach – Uriel Arvizu Jan 09 '13 at 00:38
  • To create a foreign key property add a new scalar property on the dependent side and then double click on the relation ship and set the properties accordingly (take a look at this tutorial for more details http://msdn.microsoft.com/en-us/subscriptions/jj713299.aspx). Alternatively you can hack it a bit. Since the database should not change regardless of having/not having foreign key properties in model you could try creating the model from the database you previously created-make sure you check the "create foreign keys" (or something like this) checkbox. Also backup your model just in case... – Pawel Jan 09 '13 at 07:00
  • and what about a case where I have a User entity? a User can create and update regions or clusters, how does the relationship for that cse is built? – Uriel Arvizu Jan 09 '13 at 17:09
  • I followed your suggestion and added the foreign keys and I tried to add a cluster, I sent the RegionId but I got a DbUpdateException error, [here](http://pastebin.com/JWMLWduu), my UriTemplate is like this `/cluster/new?Data={data}` and what I'm sending in data is {"RegionId":1} – Uriel Arvizu Jan 09 '13 at 18:13
  • And what the DbUpdateException actually said? Any inner exception? Stack trace? I think DbUpdateException is thrown from EF so your query made it through the DataService layer which seems a good sign. – Pawel Jan 09 '13 at 18:30
  • [here](http://pastebin.com/JWMLWduu) is the link for the exception – Uriel Arvizu Jan 09 '13 at 18:34
  • Are you sure that there is a row in the corresponding table with the ID you are trying to insert as the foreign key? – Pawel Jan 09 '13 at 19:36
  • I remade the associations and now it works, maybe something wasn't mapping right, with that solved, can you tell me what to do when there're more than one association between two entities? Like the example I presented with a user being able to create clusters and update clusters – Uriel Arvizu Jan 09 '13 at 20:15
  • You can have multiple navigation properties and multiple foreign keys. In the example about Users and Clusters I don't know what kind of relationship you were talking about so it is hard to tell (e.g. if it is many to many then you will not have foreign keys exposed and you need to update relationships directly by using $links query, otherwise you would have another foreign key and navigation property for the other Assoction) – Pawel Jan 09 '13 at 20:51
  • for a example a User can create a cluster and can update a cluster, so a cluster would have a property CreatedBy and UpdatedBy that should reference the User involved – Uriel Arvizu Jan 11 '13 at 00:55
  • You would just have another two navigation properties for each user and another two foreign key properties. – Pawel Jan 11 '13 at 01:43

1 Answers1

0

From what I gather, you have two methods of saving your cluseters. The first one is as a byproduct of the saving or regions. If you have basic CRUD WCF endpoints, you can simply construct your Region entity in your client, add the clusters, and then call the save.

var reg = new Region();
//set region properties
//build clusters set
for (int i = 0; i<5; i++)
    reg.Clusters.add (new Cluster {CreatedDateTime= DateTime.Now, 
                                   UpdatedDateTime = DateTime.Now});

wcfClient.SaveRegion(reg); //<-- if the back-end works with EF, this should be able 
                           //to insert one new region with five new clusters

Your other option is to save clusters through a WCF endpoint that is designed to save clusters themselves. Before doing this, I would recommend that you modify your Clusters entity to explicitly have a RegionId field.

public partial class Clusters
{

    public int ClusterId { get; set; }
    public System.DateTime CreatedDateTime { get; set; }
    public System.DateTime UpdatedDateTime { get; set; }

    public int RegionsId {get; set;}
    public virtual Regions Region { get; set; }
}

Entity framework should be able to recognize automatically that the RegionsId corresponds to the primary key of the Regions entity. After this, it's just a matter of making sure that every Cluster you create has a proper RegionsId property. When you call your "wcfClient.SaveCluster(cluster)" method, EF would automatically link that cluster to the proper region.

Jeric Cantos
  • 278
  • 1
  • 7
  • so if my model is exposed to foreign keys, if I send the RegionId on my JSON string, then insert that into a Cluster object and then save that Cluster object, will the relationship between the two entities make sure that RegionId belong to an existing entry on Region? – Uriel Arvizu Jan 09 '13 at 17:08
  • Yes. That's the way we do it in our projects. The key is having good CRUD methods that accept any Entity in your system. In the end, the goal is to have a call to something like: "context.Set().Insert(clusterObj);" as long as the clusterObj contains the "regionsId" field, it will be properly inserted into the database and the relationships can be traversed. Also, note that you can make use of Data Annotations to specify field properties like "Required" or "Max Length". It would help in data integrity validations done for you automatically by EF – Jeric Cantos Jan 10 '13 at 05:06
  • but I'm using Model First approach, can I use Data Annotations with that? I'm new to working with EF – Uriel Arvizu Jan 11 '13 at 00:56
  • The save mechanism should be the same. I believe your problem is that you're just hesitating to modify the code that's generated by your model, right? Here's a good read on how to customize and modify your Model-First Approach. The Region - Clusters relationship is similar to the Customer - Flight relationship in this paper: http://msdn.microsoft.com/en-us/data/ff830362.aspx – Jeric Cantos Jan 11 '13 at 05:12