[CSHARP-100] CSharp driver exception when Saving a an object with an IList<T> property as opposed to List<T> Created: 17/Nov/10 Updated: 02/Apr/15 Resolved: 17/Nov/10 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | None |
| Affects Version/s: | 0.9 |
| Fix Version/s: | 0.9 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Justin Dearing | Assignee: | Robert Stam |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Visual Studio 2008 |
||
| Description |
|
Long story short, if I call MongoCollection.Save<T>() on a class with Long Explanation where I take actual code, and scrub it: So I have class that kinda looks like this: [DataContract] } And then I do something like this: var obj = new ChildClass{ SomeProperty = new List<SomeClass>(); }; _db["someCollection"].Save(obj, SafeMode.True); Then I get the following GenericArraySerializer cannot be used with type: System.Collections.Generic.IList`1[[SomeClass, SomeAssembly Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] at MongoDB.Bson.DefaultSerializer.GenericArraySerializer.VerifyNominalType(Type nominalType) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer\\Serializers GenericArraySerializer.cs:line 113\r\n at MongoDB.Bson.DefaultSerializer.GenericArraySerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer\\Serializers GenericArraySerializer.cs:line 83\r\n at MongoDB.Bson.DefaultSerializer.BsonClassMapSerializer.SerializeMember(BsonWriter bsonWriter, Object obj, BsonMemberMap memberMap) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer BsonClassMapSerializer.cs:line 221\r\n at MongoDB.Bson.DefaultSerializer.BsonClassMapSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer BsonClassMapSerializer.cs:line 181\r\n at MongoDB.Bson.Serialization.BsonSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\Serialization BsonSerializer.cs:line 245\r\n at MongoDB.Bson.Serialization.BsonSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value) in d: justin's projects\\mongo-csharp\\Bson\\Serialization BsonSerializer.cs:line 229\r\n at MongoDB.Bson.DefaultSerializer.EnumerableSerializer`1.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer\\Serializers CollectionSerializersGeneric.cs:line 89\r\n at MongoDB.Bson.DefaultSerializer.BsonClassMapSerializer.SerializeMember(BsonWriter bsonWriter, Object obj, BsonMemberMap memberMap) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer BsonClassMapSerializer.cs:line 221\r\n at MongoDB.Bson.DefaultSerializer.BsonClassMapSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer BsonClassMapSerializer.cs:line 181\r\n at MongoDB.Bson.Serialization.BsonSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\Serialization BsonSerializer.cs:line 245\r\n at MongoDB.Bson.Serialization.BsonSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value) in d: justin's projects\\mongo-csharp\\Bson\\Serialization BsonSerializer.cs:line 229\r\n at MongoDB.Bson.DefaultSerializer.EnumerableSerializer`1.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer\\Serializers CollectionSerializersGeneric.cs:line 89\r\n at MongoDB.Bson.DefaultSerializer.BsonClassMapSerializer.SerializeMember(BsonWriter bsonWriter, Object obj, BsonMemberMap memberMap) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer BsonClassMapSerializer.cs:line 221\r\n at MongoDB.Bson.DefaultSerializer.BsonClassMapSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\DefaultSerializer BsonClassMapSerializer.cs:line 181\r\n at MongoDB.Bson.Serialization.BsonSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\Serialization BsonSerializer.cs:line 245\r\n at MongoDB.Bson.Serialization.BsonSerializer.Serialize[T](BsonWriter bsonWriter, T value, Boolean serializeIdFirst) in d: justin's projects\\mongo-csharp\\Bson\\Serialization BsonSerializer.cs:line 221\r\n at MongoDB.Driver.Internal.MongoUpdateMessage`2.WriteBody() in d: justin's projects\\mongo-csharp\\Driver\\Internal MongoUpdateMessage.cs:line 58\r\n at MongoDB.Driver.Internal.MongoRequestMessage.WriteToBuffer() in d: justin's projects\\mongo-csharp\\Driver\\Internal MongoRequestMessage.cs:line 81\r\n at MongoDB.Driver.Internal.MongoConnection.SendMessage(MongoRequestMessage message, SafeMode safeMode) in d: justin's projects\\mongo-csharp\\Driver\\Internal MongoConnection.cs:line 324\r\n at MongoDB.Driver.MongoCollection.Update[TQuery,TUpdate](TQuery query, TUpdate update, UpdateFlags flags, SafeMode safeMode) in d: justin's projects\\mongo-csharp\\Driver\\Core MongoCollection.cs:line 662\r\n at MongoDB.Driver.MongoCollection.Save[TDocument](TDocument document, SafeMode safeMode) in d: justin's projects\\mongo-csharp\\Driver\\Core MongoCollection.cs:line 584\r\n at ... ... ... My Code ....... So the fix is as follows: [DataContract] public class ChildClass : ParentClass { [BsonIgnoreIfNull] [DataMember(Order = 1)] - [BsonKnownTypes(typeof(List<SomeClass>))] - public IList<SomeClass> SomeProperty { get; set; } + public List<SomeClass> SomeProperty { get; set; }} |
| Comments |
| Comment by Robert Stam [ 17/Nov/10 ] |
|
Fixed. Also improved implementation of ArraySerializer (no Invoke any more). |
| Comment by Justin Dearing [ 17/Nov/10 ] |
|
It took me a bit to understand your comment. I didn't know and IList<T> could hold an array, but the MSDN verified it. The problem for me is that WCF is the real culprit, I'm passing a request contract to th I actually have no need to use IList<T> as opposed to List<T>, I was just trying to be all polymorphic and using the interface since that seemed like "The Right Thing To Do"™. So changing from IList<T> to List<T> is my quick workaround for me. Seeing this WCF behavior, and the implications, like SomeProperty.Add() throwing NotImplementedException(), I might end up sticking with List<T> for the long term. |
| Comment by Robert Stam [ 17/Nov/10 ] |
|
Was able to reproduce by adding these two lines: obj = new ChildClass { SomeProperty = new [] { new SomeClass(), new SomeClass() } }; so an easy workaround while this gets fixed is to use Lists instead of arrays when initializing SomeProperty. |
| Comment by Robert Stam [ 17/Nov/10 ] |
|
I added a unit test for this (CSharp100Tests.cs. under DriverOnlineTests). You can mess with the unit test and see if you can make it fail. Perhaps I didn't duplicate your scenario faithfully enough. |
| Comment by Robert Stam [ 17/Nov/10 ] |
|
I tried to reproduce and wasn't able to. Here's part of the code I wrote: collection.RemoveAll(); ; ; }; }; and here's what the collection looked like in the shell: > db.csharpxx.find() { "_id" : ObjectId("4ce42b7fe447ad36fc456185") } { "_id" : ObjectId("4ce42b7fe447ad36fc456186"), "SomeProperty" : [ ] }{ "_id" : ObjectId("4ce42b7fe447ad36fc456187"), "SomeProperty" : |