Describe the bug
NullReferenceException if no parameterless constructor for a generic list element
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at LiteDB.BsonValue.get_AsDateTime() in D:\code\LiteDB\LiteDB\Document\BsonValue.cs:line 241
at LiteDB.BsonMapper.<>c.<.ctor>b__37_7(BsonValue bson) in D:\code\LiteDB\LiteDB\Client\Mapper\BsonMapper.cs:line 129
at LiteDB.BsonMapper.<>c__DisplayClass38_0`1.<RegisterType>b__1(BsonValue b) in D:\code\LiteDB\LiteDB\Client\Mapper\BsonMapper.cs:line 149
at lambda_method(Closure , BsonDocument )
at LiteDB.BsonMapper.Deserialize(Type type, BsonValue value) in D:\code\LiteDB\LiteDB\Client\Mapper\BsonMapper.Deserialize.cs:line 198
at LiteDB.BsonMapper.DeserializeList(Type type, BsonArray value) in D:\code\LiteDB\LiteDB\Client\Mapper\BsonMapper.Deserialize.cs:line 258
at LiteDB.BsonMapper.Deserialize(Type type, BsonValue value) in D:\code\LiteDB\LiteDB\Client\Mapper\BsonMapper.Deserialize.cs:line 158
at LiteDB.BsonMapper.DeserializeObject(EntityMapper entity, Object obj, BsonDocument value) in D:\code\LiteDB\LiteDB\Client\Mapper\BsonMapper.Deserialize.cs:line 299
at LiteDB.BsonMapper.Deserialize(Type type, BsonValue value) in D:\code\LiteDB\LiteDB\Client\Mapper\BsonMapper.Deserialize.cs:line 220
at LiteDB.LiteQueryable`1.<ToEnumerable>b__27_2(BsonDocument x) in D:\code\LiteDB\LiteDB\Client\Database\LiteQueryable.cs:line 269
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at Program.Main(String[] args) in D:\code\LiteDB\ConsoleTest\Program.cs:line 44
Code to Reproduce
using LiteDB;
using System;
using System.Collections.Generic;
using System.IO;
class DataContainer
{
public DateTimeOffset Date { get; set; }
public DataContainer(DateTimeOffset dateTime) => Date = dateTime;
//public DataContainer() { }
// Uncomment this for no errors
}
class Player
{
[BsonId(false)]
public Guid Id { set; get; }
public List<DataContainer> Data { set; get; } = new List<DataContainer>();
}
class Program
{
static void Main(string[] args)
{
var player = new Player()
{
Id = Guid.NewGuid(),
Data = new List<DataContainer>
{
new DataContainer(DateTimeOffset.Now)
}
};
using (var db = new LiteDatabase(new MemoryStream()))
{
var col = db.GetCollection<Player>();
col.DeleteAll();
col.Upsert(player);
foreach (var i in col.FindAll())
{
Console.WriteLine(i.Id);
Console.WriteLine(i.Data.Count);
}
}
Console.ReadLine();
}
}
Expected behavior
Not sure if this is expected behavior, but can it be handled better?
after going through the source code, you have two choices:
add a default constructor
change the property name in DataContainer: "Date" -> "dateTime", after change, because when constructing the object with its constructor, it will search 'dateTime' in the doc(BsonDocument), but there's no such field because you only persisted a field named "Date".
I think this is a defect when not providing a default constructor to re-construct the object from the document, this should be taken as a specification, just like java's serialized specification.
LiteDB should not provide a way to construct an object from its params constructor, because it has so much limitations to function
Version LiteDB 5.0.12
Describe the bug NullReferenceException if no parameterless constructor for a generic list element
Code to Reproduce
Expected behavior Not sure if this is expected behavior, but can it be handled better?