I'm having a lot of troubles with RIA Services. I'm really wondering if it's worth the hassle at all. The problem I have now is similar to other problems: related entities. Let's say I have a class, Foo. Foo has two related entities, Bar and Fighter.
If I'm working on a new Foo, foo, and I want to add something to the Bars collection, it works just fine. Like:
foo.Bars.Add(new Bar{A=a, B=b});
But when I try to add a Fighter, it doesn't work:
foo.Fighters.Add(new Fighter{C=c,D=d});
I've been all around the interwebz looking for the solution. I've found the suggestions to use the [Include] attribute and the [Associated] attribute as well. Both have worked in some cases. But they're not working in this case and I have zero clue why. I've deleted and re-created my EDMX and my DomainService because someone suggested it, but it isn't working.
So what is wrong and what other information do you need to help me out? When I say try to add a Fighter to my foo.Fighters collection, it's not persisting the add. I will note that I'm trying to add an existing Fighter in my specific example, not a new Fighter, if that helps/gives clues.
If you need information or real code samples, I'll be happy to oblige. Thanks in advance to all that try to help.
A number of things to check and confirm
The Fighter table has a foreign key defined in the database.
Use [Association], [Include], and [Composition] attributes. Association defines the relationship. Include instructs the server to send the instance or contents of the collection to the client, if populated. Composition instructs WCF RIA to track changes to the collection and send them back to the server.
Ensure you are calling context.SubmitChanges() after all the adds in Silverlight.
Ensure you have an insert method on your DomainService.
Maybe one or more of these will help.
Related
I have these DB tables:
volunteers
services
services_volunteers
I baked the models, controllers and views. Now in a particular function in the volunteers controller I want to access the service_volunteers model to create a record so I do:
$this->loadModel('ServicesVolunteer');
$this->ServicesVolunteer->create();
$this->ServicesVolunteer->save(array('ServicesVolunteer'=>array('ServicesVolunteer.volunteer_id'=>$this->Volunteer->id, 'ServicesVolunteer.service_id'=>$id)));
However this isn't working for some reason. I'm stuck coz I'm pretty sure I've done similar things plenty of times before and I can't see what's going wrong. I've tested and it looks like the model loads ok, but if I wrap the create() method in an IF statement I can see it doesn't seem to fire
anyone any ideas? would be gratefully received!
How are folks generally handling the whitelisting of foreign key values? Let's ignore the use case of an associated user record which brings an additional set of issues and stick to a fairly benign scenario: A Task belongs to a Project. When I create the task, I want to create it with its project_id value, but I don't want that value to be editable. The property is passed by a hidden field in the shared form.
I know I could just unset that property in the controller before calling save() in the edit action, but I was wondering whether anyone had a better solution. I've used/tried several, but all are laborious or less "universal" than I'd like.
Does anyone have a solution that they really like to solve this particular problem?
Thanks.
I handle this manually as well. The process is something like this.
Load object and show the edit screen to the user.
When user submits, take the primary ID and load the object again. Check ownership.
Have a whitelist of user editable fields, loop through those keys and populate your new object, leave everything else alone.
Save.
You could move this into some kind of before save hook or behavior I would say. But this seems the best practice with the RoR feature (we all know what happened in GitHub)
I'm working on a personal project using WPF with Entity Framework and Self Tracking Entities. I have a WCF web service which exposes some methods for the CRUD operations. Today I decided to do some tests and to see what actually travels over this service and even though I expected something like this, I got really disappointed. The problem is that for a simple update (or delete) operation for just one object - lets say Category I send to the server the whole object graph, including all of its parent categories, their items, child categories and their items, etc. I my case it was a 170 KB xml file on a really small database (2 main categories and about 20 total and about 60 items). I can't imagine what will happen if I have a really big database.
I tried to google for some articles concerning traffic optimization with STE, but with no success, so I decided to ask here if somebody has done something similar, knows some good practices, etc.
One of the possible ways I came out with is to get the data I need per object with more service calls:
return context.Categories.ToList();//only the categories
...
return context.Items.ToList();//only the items
Instead of:
return context.Categories.Include("Items").ToList();
This way the categories and the items will be separated and when making changes or deleting some objects the data sent over the wire will be less.
Has any of you faced a similar problem and how did you solve it or did you solve it?
We've encountered similiar challenges. First of all, as you already mentioned, is to keep the entities as small as possible (as dictated by the desired client functionality). And second, when sending entities back over the wire to be persisted: strip all navigation properties (nested objects) when they haven't changed. This sounds very simple but is not at all trivial. What we do is to recursively dig into the entities present in trackable collections of say the "topmost" entity (and their trackable collections, and theirs, and...) and remove them when their ChangeTracking state is "Unchanged". But be carefull with this, because in some cases you still need these entities because they have been removed or added to trackable collections of their parent entity (so then you shouldn't remove them).
This, what we call "StripEntity", is also mentioned (not with any code sample or whatsoever) in Julie Lerman's - Programming Entity Framework.
And although it might not be as efficient as a more purist kind of approach, the use of STE's saves a lot of code for queries against the database. We are not in need for optimal performance in a high traffic situation, so STE's suit our needs and takes away a lot of code to communicate with the database. You have to decide for your situation what the "best" solution is. Good luck!
You can find an Entity Framework project item at http://selftrackingentity.codeplex.com/. With version 0.9.8, I added a method called GetObjectGraphChanges() that returns an optimized entity object graph with only objects that have changes.
Also, there are two helper methods: EstimateObjectGraphSize() and EstimateObjectGraphChangeSize(). The first method returns the estimate size of the whole entity object along with its object graph; and the later returns the estimate size of the optimized entity object graph with only object that have changes. With these two helper methods, you can decide whether it makes sense to call GetObjectGraphChanges() or not.
I'm new to Silverlight, but being dumped right into the fray - good way to learn I suppose :o)
Anyway, the webapp I'm working on has a relatively complex database structure that represents various object types that are linked to each other, and I was wondering 2 things:
1- What is the recommended approach when it comes to dataclasses? Have just one big dataclass, or try and separate it into several smaller dataclasses, keeping in mind they will need to reference each other?
2- If the recommended approach is to have several dataclasses, how do you define the inter-dataclasses references?
I'm asking because I did a small test. In my DB (simplified here, real model is more complex but that's not important), I have a table "Orders" and a table "Parameters". "Orders" has a foreign key on "Parameters". What I did is create 2 dataclasses.
The first one, ParamClass, were I dropped the "Parameters" table only, so I can have a nice "parameter" class. I then created a simple service to add basic SELECT and INSERT functionality.
The second one, OrdersClass, where I dropped both tables, so that the relation between the tables would automatically create a "EntityRef<parameter>" variable inside the "order" class. I then removed the "parameters" class that was automatically created in the OrdersClass dataclass, since the class has already been declared in the ParamClass dataclass. Again I created a small service to test it.
So far so good, it builds happily. The problem is that when I try to handle things on the application code, I added service references for both dataclasses, but it is not happy doing something like:
OrdersServiceReference.order myOrder = new OrdersServiceReference.order();
myOrder.parameter = new ParamServiceReference.parameter(); //<-PROBLEM IS HERE
It comlpains that it cannot implicitly convert from type 'MytestDC.ParamServiceReference.parameter' to 'MytestDC.OrdersServiceReference.parameter'
Do I somehow need to declare some sort of reference to ParamClass from OrdersClass, or how do I "convert" one to the other?
Is this even a recommended and efficient way of doing this?
Since it's a team-project, I initially wanted to separate the dataclasses so that they (and their services) can be easily checked out by one member without checking out the whole entire dataclass.
Any help appreciated!
PS: using Silverlight 4, in case that's important
Based on the widely accepted Single Responsability Principle (SRP), a class should always be responsible for one task, and one task only.
That pretty much invalidates your "one big dataclass" approach.
I would always recommend smaller, more manageable bits that can be combined, instead of one humonguous class that does everything (except brew coffee for you).
Resources for the SRP:
Wikipedia on SRP
OODesign: Single Responsibility Principle
ObjectMentor: list of articles on good app design - which has a few links to PDF documents, like this one on SRP written by Robert C. Martin - the "guru" on proper OO design
OK, some more research let me to this: it is not simple to separate classes from a relational model using LINQtoSQL. I ended up switching to an Entity Framework approach, which itself doesn't deal with it gracefully (see here and there, for example), but at least it solved another major problem I had with LINQtoSQL.
There are other ORMs out there that are apparently much more capable at this (NHibernate comes up often in recommendations), unfortunately, I don't have time to investigate them now, being under such a tight deadline.
As for the referencing, it was quite simple, change the line to:
myOrder.parameter = new OrderServiceReference.parameter();
even though I removed the declaration from that dataclass.
Hope this helps someone!
I've finally managed to get a handle on loading information using Silverlight, ADO.NET Entities, and RIA Services, but I'm still having a problem with getting the information about the relationships.
For instance, imagine a product, and that product has several categories of attributes. We'll call them ProductAreas.
The Product object has a property called ProductAreas (as a result of their relationship), but when I call:
ctx.Load(GetProductsQuery());
(Where ctx is my DomainContext), the Product objects returned have the ProductAreas property, but it contains no elements, which is a very serious problem, in my case.
So the question is: How do I get access to these relationships?
I'm not sure what your GetProductsQuery() method does, but you should be able use the .Include('ProductAreas') method in your query. If you update your question with the contents of that method I'll try to help more.
This isn't technically the way this system is supposed to work, but I wanted to expand on your answer, while at the same time giving it the credit it rightfully deserves for leading me where I needed to be.
The solutions was to, in the GetProductsQuery() method use
return this.ObjectContext.Products.Include("ProductAreas");
instead of
return this.ObjectContext.Products;
And in the metadata file, go to the Products class and, just above the ProductAreas property add [Include()], so that it looks like:
[Include()]
public EntityCollection<ProductAreas> ProductAreas;