How to pass a collection of Entities to .NET RIA Data Service? - silverlight

Is it possible to pass a collection of objects to a RIA Data Service query? I have no issues sending an Entity, an Int or an array of primitive types, but as soon as i declare a method like this
public void GetLessonsConflicts(Lesson[] lessons)
{
}
i get a compilation error
" Operation named
'GetLessonsConflicts' does not conform
to the required signature. Parameter
types must be an entity type or one of
the predefined serializable
types"
I am just trying to do some validation on the server side before i save the data. I've tried List, IEnumerable etc.
Thanks

I think the problem is actually the lack of a return value. As I understand it, you can identify DomainOperations by convention or by attribute. You're not showing an attribute so RIA will be trying to match it by convention.
For example, by convention, an insert method must:
have Insert, Add or Create as the method name prefix, e.g. InsertEmployee
match the signature public void name(Entity e);
a query method must:
be public
return IEnumerable, IQueryable or T (where T is an entity).
a custom domain operation must
be public
return void
have an Entity as the first parameter.
EDIT: See Rami A's comment below. I believe this was true at the time but I'm not currently working with this technology so I'm not current enough on it to update this answer other than to note that it may be incorrect.
Or you can use Attributes such as [Insert],[Delete],[Update],[Query],[Custom]. From my docs, all the attributes do is remove the requirement for the name convention - it's not clear from them, to me, what the [Query] and [Custom] attributes achieve.
As well as DomainOperations, you can define ServiceOperations (using the [ServiceOperation] attribute) and InvokeOperations.
This article might help (although I think it's a bit out of date).

Related

OOP composition and orm

I am building a simple rate limiter to train my oop skills and I am having some doubts regarding composition and orm.
I have the following code:
interface RateLimiterService {
void hit(String userid, long timestamp) throws UserDoesNotExistEx, TooManyHitsEx; // Option A
SingleRateLimiter getUser(String userid) throws UserDoesNotExistEx; // Option B
Optional<SingleRateLimiter> getUser(String userid); // Option C
}
class LocalRateLimiterService implements RateLimiterService {
// Uses an hash table userid -> SingleRateLimiter
}
interface SingleRateLimiter {
void hit(long timestamp) throws TooManyHitsEx;
}
class TimestampListSRL implements SingleRateLimiter {
// Uses a list to store the timestamps and purges the expired ones at each call
}
class TokenBucketSRL implements SingleRateLimiter {
// Uses the token bucket aproach
}
My doubts are:
Which option should I use for the RateLimiterService interface?
Option A is usually called "method forwarding" or "delegation" or "Law of Demeter". It protects the composed object by only exposing the intended methods and/or by possibly adding some extra validation logic before forwarding the call. Therefore, it seems like a good solution when that is needed. However, when this is not the case (as in my example), this option creates a lot of redundant repetitions which add nothing usefull.
Option B breaks encapsulation in a way but it avoids method repetions (the DRY principle). By picking A or B you always end up breaking some well known principles/good practices. Is there another option?
Option C is the same as B but returns an optional instead of throwing an exception. Which approach is considered better?
If the classes that implement the RateLimiterService had a single composing SingleRateLimiter instead of a collection of SingleRateLimiters (doesn't make much sense in this case but trying to be generic to other situations when the composed object is not a colection), would the best Option change to other alternative from the one in 1.?
If I wanted to add a database to this system, what would be the best approach to "talk to" the database?
creating a class DBRateLimiterService that implements RateLimiterService and has a private connection object to the database (is basically a DAO)? In this case, this class does not know anything besides the userid of the inner SingleRateLimiters, since there are multiple implementations available/possible. So how can I do this approach without changing the current OOP architecture?
In addition, I would need to create a DAO for each SingleRateLimiter implementation too, right? In this case, the SingleRateLimiter is not a simple model object that has only getters and setters so it should also be a DAO, right? Its hit method must be implemented as a transaction in most cases (if not all). If this is the right approach, how can the two DAOs operate together and map to the same database table?
What other options could serve for this?

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

OOAD - Properties representing relationships between two types

I have started to model some city-transport data (bus lines and bus stops) for a community project. The data arrived to me as JSON files, and I'd like to create some classes from it, considering the already available data at first.
There is a BusLine object, whose JSONs don't contain information about which BusStop are related to it.
And there is a large collection of BusStop, of which one property is BusLines, a collection of (references to) bus lines which pass about that stop.
So far I have modelled this (C# style, but intended just for visualization at first):
public class BusLine
{
public String code;
public String name;
public List<DirectPosition> route;
}
public class BusStop
{
public String code;
public DirectPosition location;
public List<BusLine> busLines;
}
My doubt, from now, is this: most probably, I'll want to know the BusStops associated with a given BusLine. I imagine some possible ways of doing it, but am not sure at all how this rather trivial situation should be addressed. My naive thoughts:
Create a getStops() method that would look somewhere to check which stops existed along that route, and create such list on-the-fly;
Create an explicit List<BusStop> stops property in BusLine class (that sounds very wrong);
Eliminate containment altogether and create a third, "Relation" kind of class that would manage (somehow) the relations between those classes. That would mean the knowledge about those relations, extracted from the JSON files, wouldn't be stored "inside" the entities, but somewhere else.
I am pretty sure this is a common pattern (I'd bet there's at least one design pattern for that), but my current level of knowledge gives me no clue...
Thanks for any help!

Data Contract Serializer mandates super class to know about subclass

I got this problem,
"The deserializer has no knowlege of any type that maps to this contract"
After googling, I reached this post
The deserializer has no knowlege of any type that maps to this contract
where the answer says, the base class have to declare "KnownTypes" like
[DataContract, KnownType(typeof(Subclass)) ...],
If I have to declare this in my parent class, [DataContract, KnownType(typeof(Subclass))], doesn't it break the principles of OO Design that parent class doesn't have to know about subclass?
What is the right way of doing this?
The serializer is designed in a way that, if it serializes an object, it should be able to read it back. If you attempt to serialize an object with a declared type of 'Base', but an actual type of 'Derived' (see example below), if you want to be able to read back from the serialized object an instance of 'Derived', you need to somehow annotate the XML that the instance is not of the type of which it was declared.
[DataContract]
public class MyType
{
[DataMember]
public object obj = new Derived();
}
The serialized version of the type would look something like the XML below:
<MyType>
<obj actualType="Derived">
<!-- fields of the derived type -->
</obj>
</MyType>
When the type is being deserialized, the serializer will look at the "actualType" (not actual name) attribute, and it will have to find that type, initialize it, and set its properties. It's a potential security issue to let the serializer (with in Silverlight lives is a trusted assembly and has more "rights" than the normal user code) to create arbitrary type, so that's one reason for limiting the types which can be deserialized. And based on the design of the serializer (if we can serialize it, we should be able to deserialize it), the serialization fails for that reason as well.
Another problem with that is that the serialized data is often used to communicate between different services, in different computers, and possibly with different languages. It's possible (and often it is the case) that you have a class in a namespace in the client which has a similar data contract to a class in the server side, but they have different names and / or reside in different namespaces. So simply adding the CLR type name in the "actualType" attribute won't work in this scenario either (the [KnownType] attribute helps the serialzier map the data contract name / namespace to the actual CLR type). Also, if you're talking to a service in a different language / platform (i.e., Java), CLR type names don't even make sense.
Another more detailed explanation is given at the post http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx - it talks about [ServiceKnownType] instead of [KnownType], but the principles are the same.
Finally, about your question: does it break that OO principle? Yes, that principle is broken, that's a price to pay for being able to have lose coupling between the client and services in your distributed (service-oriented) application.
Yes it breaks the principles of OO design. This is because SOA is about sharing contracts (the C in ABC of services) and not types, whereas OO is about type hierarchies. Think like this the client for a service may not be even in an OO language but SOA principles can still be applied. How the mapping is done on server side is an implementation issue.

RIA Services and Relationships in Silverlight 3

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;

Resources