RIA Services and Relationships in Silverlight 3 - silverlight

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;

Related

What's the preferred way to go about using backbone with non-crud resources?

New to backbone/marionette, but I believe that I understand how to use backbone when dealing with CRUD/REST; however, consider something like results from a search query. How should one model this? Of course the results likely relate to some model(s), but they are not meant to be tied to said model(s).
Part of me thinks that I should use a collection using a model that doesn't actually sync with a data store through the server, but instead just exists as a means of a modeling a search result object.
Another solution could be to have a collection with no models and just override parse.
I assume that the former is preferred, but again I have no experience with the framework. If there's an alternative/better solution than those listed above, please advise.
I prefer having one object which is responsible for both request and response parsing. It can parse the response to appropriate models and nothing more. I mean - if some of those parsed models are required somewhere in your page, there is something that keeps reference to this wrapper object and takes models from response it requires via wrapper methods.
Another option is to have Radio (https://github.com/marionettejs/backbone.radio) in this wrapper - you will not have to keep wrapper object in different places but call for data via Radio.

When to maintain reference to key vs. reference to actual entity object after put operation.

When working with datastore entities in App Engine, people have noticed odd behavior after a put operation is performed on an entity if you choose to hold on to a reference of that entity.
For example, see this issue where repeated String properties mutated to _BaseValue after a put was performed.
In the ensuing discussion, in reference to a repeated String property, Guido van Rossum writes:
"I see. We should probably document that you're not supposed to hang
on to the list of items for too long; there are various forms of
undefined behavior around that."
I get the sense from this thread that it's not a good idea to maintain reference to an entity for too long after a put, as unexpected behavior might arise.
However, when I look at the GAE source code for the Model.get_or_insert() method, I see the following code (docstring removed):
#classmethod
def get_or_insert(cls, key_name, **kwds):
def txn():
entity = cls.get_by_key_name(key_name, parent=kwds.get('parent'))
if entity is None:
entity = cls(key_name=key_name, **kwds)
entity.put()
return entity
return run_in_transaction(txn)
Notice how a put operation is performed, and the entity is returned post-put. Just above, we saw an example of when this is not recommended.
Can anyone clarify when and when it is not ok to maintain a reference to an entity, post put? Guido seemed to hint that there are various scenarios when this could be a bad idea. Just curious if anyone has seen documentation on this (I cannot find any).
Thanks!
The problem described in the issue is not regarding entities, but rather lists obtained from its properties. You can hold a copy of entity as long as you like. It's just an object.
The issue is caused by some "magical" functionality provided by ndb. Let's take a look at the model definition
from google.appengine.ext.ndb import model
class MyModel(model.Model):
items = model.StringProperty(repeated=True)
What can we say about items property?
It looks like a class attribute, but metaclass logic of model.Model transforms it into an instance attribute.
What type are these instance attributes?
They can be accessed like a list of strings, but they are more complex objects having the logic required for storing and retrieving the data from datastore, validating etc.
This "magic" works well in most cases, but sometimes it doesn't. One of the problematic cases is when you get the reference to items from the instance and try to use it after put was called. Another case, mentioned by Guido, was to pass external list to initialize items property and then try to modify this property by manipulating the external list.
The thing to remember: Model properties in ndb try to behave like their basic types, but they are more complex objects. You can read more about their internals in Writing property subclasses

Calling WCF services in MVVM?

I am working on a Prism desktop application and would like to know the best way to deal with lookup / reference data lists when using a WCF backend. I think this question may cover a few areas and I would appreciate some guidance
For example, consider a lookup that contains Products(codes and descriptions) which would be used in a lot of different input screens in the system.
Does the viewmodel call the WCF service directly to obtain the data to fill the control?
Would you create a control that solely deals with Products with its own viewmodel etc and then use that in every place that needs a product lookup or would you re-implements say a combobox that repopulates the products ItemsSource in every single form view model that uses it?
Would I create a brand new WCF service called something like LookupData service and use that to populate my lookup lists? - I am concerned I will end up with lots of lookups if I do this.
What other approaches are there for going about this?
I suggest creating your lookup object/component as a proxy object for WCF service. It can work in several ways, but most simple coming to my mind would be:
Implement WCF service with methods to provide all Products entities and requested one (eg. basing on product code)
Implement component that will use WCF client to get products, let's call it ProductsProvider
Your view models will take dependency on ProductsProvider (eg. via constructor injection)
Key element in this model is ProductsProvider - it will work as kind of cache for Products objects. First, it will ask web service for all products (or some part of it, up to your liking) to start with. Then, whenever you need to lookup product, you ask provider - it's provider's responsibility to deal with how product should be looked up - maybe it's already in local list? Maybe it will need to call web service for update? Example:
public class ProductsProvider
{
private IList<Product> products;
private IProductsService serviceClient;
public ProductsProvider(IProductsService serviceClient)
{
this.serviceClient = serviceClient;
this.products = serviceClient.GetAllProducts();
}
public Product LookUpProduct(string code)
{
// 1: check if our local list contains product with given code
// 2: if it does not, call this.serviceClient.LookUpProduct
// 3: if service also doesn't know such product:
// throw, return null, report error
}
}
Now, what this gives you is:
you only need to have one ProductsProvider instance
better flexibility with when and how your service is called
your view models won't have to deal with WCF at all
Edit:
As for your second question. Control may not be needed, but having view model for Product entity is definitely a good idea.

Self Tracking Entities Traffic Optimization

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.

Why Do Some Related Entities Persist and Not Others in RIA Services?

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.

Resources