LiteDB
LiteDB copied to clipboard
[BUG] Cannot serialize Record (C# 9)
Version 5.0.11 / Xamarin.Forms Android
Describe the bug
LiteDB.LiteException: Failed to create instance for type 'CovaSud.TeamCollect.Domain.Tours.TourInfo' from assembly
ERROR|1|App|Error in wrapped task --> LiteDB.LiteException: Failed to create instance for type 'CovaSud.TeamCollect.Domain.Tours.TourInfo' from assembly 'CovaSud.TeamCollect.Domain.Tours.TourInfo, TeamCollect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Checks if the class has a public constructor with no parameters. ---> System.ArgumentException: Type 'CovaSud.TeamCollect.Domain.Tours.TourInfo' does not have a default constructor
Parameter name: type
at System.Linq.Expressions.Expression.New (System.Type type) [0x00070] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/NewExpression.cs:196
at LiteDB.Reflection.CreateClass (System.Type type) [0x00015] in <47be80e4df11402fa4b0c9d0d61b2517>:0
at LiteDB.Reflection.CreateInstance (System.Type type) [0x00066] in <47be80e4df11402fa4b0c9d0d61b2517>:0
--- End of inner exception stack trace ---
at LiteDB.Reflection.CreateInstance (System.Type type) [0x0018f] in <47be80e4df11402fa4b0c9d0d61b2517>:0
at LiteDB.BsonMapper+<>c__DisplayClass59_0.<Deserialize>b__0 (LiteDB.BsonDocument v) [0x0000b] in <47be80e4df11402fa4b0c9d0d61b2517>:0
at LiteDB.BsonMapper.Deserialize (System.Type type, LiteDB.BsonValue value) [0x00246] in <47be80e4df11402fa4b0c9d0d61b2517>:0
at LiteDB.LiteQueryable`1[T].<ToEnumerable>b__27_2 (LiteDB.BsonDocument x) [0x00000] in <47be80e4df11402fa4b0c9d0d61b2517>:0
at System.Linq.Enumerable+SelectEnumerableIterator`2[TSource,TResult].MoveNext () [0x00036] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Linq/src/System/Linq/Select.cs:131
at System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable`1[T] source, System.Boolean& found) [0x00045] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Linq/src/System/Linq/First.cs:63
at System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable`1[T] source) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Linq/src/System/Linq/First.cs:34
at LiteDB.LiteQueryable`1[T].FirstOrDefault () [0x00006] in <47be80e4df11402fa4b0c9d0d61b2517>:0
at CovaSud.TeamCollect.Domain.Tours.Impl.TourLocalRepository+<>c__DisplayClass6_0.<TryGetTour>b__0 () [0x00038] in D:\Dev\CovaSud\TeamCollect\TeamCollect\Domain\Tours\Impl\TourLocalRepository.cs:32
at CovaSud.TeamCollect.Domain.Tours.Impl.TourService.GetTour (System.Int32 tourId, System.DateTime tourDate, System.Boolean refresh) [0x0009f] in D:\Dev\CovaSud\TeamCollect\TeamCollect\Domain\Tours\Impl\TourService.cs:41
at CovaSud.TeamCollect.Presentation.Pages.Collections.Tours.TourPageViewModel.LoadTour (System.Boolean refresh) [0x0006f] in D:\Dev\CovaSud\TeamCollect\TeamCollect\Presentation\Pages\Collections\Tours\TourPageViewModel.cs:116
at Sharpnado.Tasks.TaskMonitorBase.MonitorTaskAsync () [0x0011e] in <9c7e2c92bb6e40e591c251583aa12e08>:0
Code to Reproduce
Try to serialize a simple Record object:
public record TourInfo(
int Id,
Sector? Sector,
Collector Collector,
TourState TourState,
string? Name,
DateTime Date,
List<int> SortedCollectionIdList)
{
}
I have a similar issue. In my case, I am working in F# (.NET 6.0) and using v.5.0.11 of the library. I am using a record object. It seems to get added to the database collection, but finding it again produces the reported error.
@roubachof Try doing the little bit more verbose version with init
setters so that a default parameter-less constructor is created:
public record TourInfo()
{
public int Id { get; init; }
public Sector? Sector { get; init; }
public Collector Collector { get; init; }
public TourState TourState { get; init; }
public string? Name { get; init; }
public DateTime Date { get; init; }
public List<int> SortedCollectionIdList { get; init; }
}
See if that works for you. This still gives the benefit of the immutable structure but is a little longer.
hey @broknecho ! We changed our database since records and immutability is the base of our architecture, I'm afraid I won't be able to test this workaround (and I guess we wouldn't consider it acceptable :)
@roubachof But that's init-only setter, ie setters available only on costructor level - same code as yours, just with another syntax
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/init#motivation
Argh, I see - it does not require them to set, just alllow
I know it's only a syntax issue, but the construction declaration syntax is so much concise and readable I won't trade it vs something as verbose as init declaration, which is just, awful...
Issue seems to happen only with reference type positional parameters of a record type. Only workaround I found is refactor its to required init properties:
public record TourInfo(int Id, string Name)
{
public required Sector Sector { get; init; }
}
In my case it fails with the nullable values...