Serializing data using IEnumerable<T> with WebGet - ienumerable

possible duplicate:
Cannot serialize parameter of type ‘System.Linq.Enumerable… ’ when using WCF, LINQ, JSON
Hi,
If my method signiature looks like this, it works fine.
[WebGet]
MyClass[] WebMethod()
If the signiature looks like this
[WebGet]
IEnumerable<T> WebMethod()
I get the following error:
Cannot serialize parameter of type 'X.Y.Z.T+<WebMethod>d__2c' (for operation 'WebMethod', contract 'IService') because it is not the exact type 'System.Collections.Generic.IEnumerable`1[X.Y.Z.T]' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute.
I have tried adding.
ServiceKnownType(typeof(IEnumerable))
Same error.
Is this a bug in 2010 beta 2, or is this likely to be correct going forward?
Thanks

The iterator types generated by the C# compiler are not serializable and never will be.
If you read this page, you'll see that it wouldn't make sense to serialize the iterator.
You need to return an array.
EDIT: The simplest way to do that is to move your iterator to a seperate method, and change WebMethod to
[WebGet]
MyClass[] WebMethod() { return OtherMethod().ToArray(); }

I've run into the same issue, and in my case it's simply not possible to change my entire object graph from iterator-based IEnumerable to concrete types. I simply cannot afford the memory to convert over to concrete types like List or Array. Additionally, what about the case where I return an IEnumerable of some object that has an IEnumerable property. It is unacceptable that I have to recurse my entire object graph converting all IEnumerables.
I don't see any good reason why the DataContractSerializer can't iterate any IEnumerable type and render its elements to XML in the same manner as any other collection type, even if the IEnumerable doesn't have a concrete backing type.
This is a bug which should be fixed.

Related

Is IEnumerable<object> the proper container for generic data sets?

Using Entity Framework, is IEnumerable the correct container to use to send back a generic data set? I.e. when I do not want to send back a list of the object, but just a generic a result set.
public IEnumerable<object> SelectPlayerFirstAndLastNameList()
{
return (from p in rlpEntities.Players select new { p.PlayerFirstName, p.PlayerLastName });
}
Thanks.
Here is the reference article, which talks about IList(inherits ICollection( and IEnumerable(Base Generic Interface for IQueryable,ICollection,List).
Here are the links which states generics & it's differences & it's usages,
Difference among IEnumerable , IQueryable, ICollection,IList, List
IEnumerable vs. ICollection vs. IQueryable vs. IList
Looking at your linq, it's about specific object & can be extended further in future. IQueryable is right fit for such scenario, as it gives client to iterate/add/remove items.
Check this link out Why use ICollection and not IEnumerable or List<T> on many-many/one-many relationships?.
It really depends on your scenario, but IEnumerable<> would be used when you need to iterate, and List<> when you need to iterate and modify or sort the data.
IEnunerable<> - http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx
List<> - http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx
You can also use generics, to pass on whatever types you are querying against, like for instance
public IEnumerable<T> SelectPlayerFirstAndLastNameList<T>()
{
return (IEnumerable<T>)(from p in rlpEntities.Players);
}
So you can pass either object, or a known defined type. To call this you would do
var x = SelectPlayerFirstAndLastNameList<YourClassHere>();
I think what you have is correct but decide for yourself whether you should use it.
From MSDN: Anonymous Types in the Remarks section:
Anonymous types are class types that derive directly from object, and
that cannot be cast to any type except object.
and
To pass an anonymous type, or a collection that contains anonymous
types, as an argument to a method, you can declare the parameter as
type object. However, doing this defeats the purpose of strong typing.
If you must store query results or pass them outside the method
boundary, consider using an ordinary named struct or class instead of
an anonymous type.

Why isn't DbSet covariant?

I have a factory function to return a DbSet(Of IItemType). The actual return type will always be an implementation IItemType, for example DbSet(Of CategoryType).
I thought covariance is supported in generics and this method would work fine, but I get an exception when I try to run my code:
Unable to cast object of type 'System.Data.Entity.DbSet1[CategoryType]' to type 'System.Data.Entity.DbSet1[IItemType]'.
DbSet<T> CANNOT be co-variant. Firstly, this is because in C#, classes cannot be co-variant...only interfaces. Secondly because DbSet<T> has both co-variant and contra-variant methods.
Take the following two examples.
DbSet<CategoryType> set = context.Set<CategoryType>();
IQueryable<IItemType> query = set.Where(x => x.Foo == Bar);
So we know for a fact that all CategoryTypes are IItemType, so we know this can always work.
However conversely try this...
DbSet<CategoryType> set = context.Set<CategoryType>();
IItemType newItemType = new ProductType();
set.Add(newItemType); // Compiler error.
Not all IItemTypes are CategoryType. So if we could cast DbSet<CategoryType> to DbSet<IItemType> we would get run time errors when adding... Since the compiler knows that this might not always work, it won't let you do the casting.
However there are interfaces that DbSet<T> does allow Co-Variance on. You can try casting it to IQueryable<IItemType> for example.
However it sounds like you are trying to query against the DbSet using a query against the interface... try the following
DbSet<CategoryType> set = context.Set<CategoryType>();
IQueryable<IItemType> cast = set.OfType<IITemType>(); //(or .Cast<>() works too)
IQueryable<IItemType> query = cast.Where(x => x ....);
It looks like they could be covariant. But there is a host of differences between in-memory programming and programming against a query provider.
For Entity Framework to materialize an object from the data store it requires its exact type and the mapping from database columns to the type's properties. An interface can represent any type and EF is not (yet) able to pick a suitable implementation itself. Maybe support for interfaces will be featured in future releases.
The same applies to casting entities to an interface in an EF query (a case I just added to my list of differences).

GWT serialization should not return interfaces: what about parameters and contained objects?

There are already a few questions regarding the fact that methods in GWT RPC should not return an interface like List, but rather a concrete class like ArrayList, because otherwise "GWT needs to include all possible implementations". See e.g. In GWT, why shouldn't a method return an interface?
Here's my question: is this limited to the return type itself? How about parameters of the method? And what if the return object contains an interface, e.g.
public class MyReturnObject implements IsSerializable {
List<String> listOfUnspecifiedType1;
List<Long> listOfUnspecifiedType2;
...
}
The examples I have seen all talk of the return type itself. I don't see why it would be a problem to return an interface, but not a problem to return an object which just wraps an interface; but maybe I am missing something?
It's clear from the linked question that it applies recursively (and as soon as you understand why you should use the most derived types as possible, it becomes obvious that it is recursive).
This is also true of method arguments, not only the return types and their fields: if you send a List<X> then GWT has to generate serialization code for all List classes: ArrayList, LinkedList, etc.
And of course the same applies to classes, not only interfaces: AbstractList is no different from List.
And because generation comes before optimization, all possible classes from the source path will be included, not only those that you use in your code; and then they come in the way of the optimization pass, as all those classes are now used by your app.
Therefore, the rule is: use the most specific types as possible. The corollary is: don't fear DTOs, don't try to send your business/domain objects at all cost.

morphia annotation

I am using mongodb with java and also morphia.
For my usecase i get collection name at run time. So i have a enum of collection names and based on some value i get the corresponding collection name from enum. My entity annotation is as follows
#entity(EnumName.getCollectionName())
But i get the following error
"The value for annotation attribute Entity.value must be a constant expression"
I am actually returning a constant expression only. Could anyone let me know what the issue is.
You can't use some something dynamic within annotations as those are "compile" time features which can't be changed afterwards. So you can only handle constants which you declared there, Enums and Classes. For this a smart compiler may be able to find out that you handle something which may never change, but most wont and will simply error as soon as they see that you're trying asign some function value to an annotation property.
I don't really understand what you're trying to do, but it somehow looks like you try to use one "generic" entity class for several concrete entities. I think this is really bad design.
If you can tell more details, we may be able to give you a proper solution for your problem.
If you simply don't know what Class you have to operate with at runtime, try this.
Declare your concrete entities and fill your enum with those Classes. At Runtime you can do Datastore.find(Enum.YOURCLASS) and morphia will query your appropriate class.

Enumerators, iterators, IEnumerable - a bit confused

I've read through the Iterators/Enumerators section of C# 3.0 in a Nutshell several times, but I'm still having a hard time grasping it. From their names, my initial thought is that an Iterator would iterate over a group of Enumerable objects. Am I on the right track? If so, then what about common generic collections, like a List<T>? Does List create/make use of an Iterator during some of its operations? Is T automatically Enumerable? Is there a cast? Does one even have anything to do with the other?
On a somewhat related note, while learning MVC, I've seen code like so:
public Article GetArticle(int id)
{
return _siteDB.Articles.SingleOrDefault(a => a.ArticleID == id);
}
public IEnumerable<Article> GetArticle(string title)
{
return _siteDB.Articles.Where(a => a.Title.StartsWith(title)).AsEnumerable<Article>();
}
What does having a return type of IEnumerable<T> give me?
EDIT: Okay, I think I'm beginning to get it. My confusion remains with Iterators. The book describes them as producers of Enumerators. I don't see where that actually happens with yield return. Does each yield create a new Enumerator?
The type IEnumerable gives you IEnumerable :)
It is an interface defining method GetEnumerator(), which returns IEnumerator. You can call the method as many times as you like and you always obtain new instance of IEnumerator.
The IEnumerator have property Current and methods MoveNext() and Reset() allowing the collection enumeration. The enumeration itself can be done by calling MoveNext() and reading the Current property if previous call of MoveNext() returns true.
Good example of implementation and usage is in documentation: http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx
From their names, my initial thought is that an Iterator would iterate over a group of Enumerable objects. Am I on the right track? If so, then what about common generic collections, like a List? Does List create/make use of an Iterator during some of its operations?
An iterator is a way to implement a method returning an IEnumerable<T> - it's really an implementation detail. Instead of having to create some custom class to enumerate through a collection, you can use an iterator to implement it, and the compiler does the hard work for you.
What does having a return type of IEnumerable give me?
This basically allows you to enumerate over the type. For example, the second method (which I would personally call GetArticles), would allow you to write:
foreach(var article in GetArticle(theTitle))
{
// Do something with article
}
Lets see if I can answer this.
So a List implements IEnumerable, and its not the T that has to implement it, anything in a list can be iterated, using a forech or for loop, for example. If you use a generic list like List, this means that what you have is a list of T where T is the object type defined by you, that means you don't have to cast it, but in the other hand you can only put objects of that same type in that list.
The code you have up there, can mean a series of thing:
1 - Any variable that implements IEnumerable will be able to hold the result of GetArticle,
Ex:
List yourList = GetArticle("test");
Queue myQueue = GetArticle("test");
2 - The actual processing of the query will be delayed. If you call Count for example, after you call the method, thats when it actually get executed/resolved.
3 - Because of number 2, if you are doing that on a DB as the code suggests, then you connection has to remain open till the time where you make use of the list, otherwise you will get an exception.
I think I have answered the questions.