Version
Which LiteDB version/OS/.NET framework version are you using. (REQUIRED)
.NET 6
LiteDB 5.0.11
PopOS (Ubuntu)
Describe the bug
When having a dictionary with a custom key type (for example a strongly typed long) it will be unable to cast/convert into the corrext type, even when you have a mapping function for said custom key.
Code to Reproduce
Models
public partial struct DiscordUserId {
public DiscordUserId(ulong value) : this((long)value){ }
public ulong UlongValue => (ulong)Value;
public long Value { get; }
public DiscordUserId(long value)
{
Value = value;
}
public static readonly DiscordUserId Empty = new DiscordUserId(0);
public bool Equals(DiscordUserId other) => this.Value.Equals(other.Value);
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is DiscordUserId other && Equals(other);
}
public override int GetHashCode() => Value.GetHashCode();
public override string ToString() => Value.ToString();
public static bool operator ==(DiscordUserId a, DiscordUserId b) => a.Equals(b);
public static bool operator !=(DiscordUserId a, DiscordUserId b) => !(a == b);
public int CompareTo(DiscordUserId other) => Value.CompareTo(other.Value);
class DiscordUserIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<DiscordUserId>
{
public override DiscordUserId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{
return new DiscordUserId(reader.GetInt32());
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, DiscordUserId value, System.Text.Json.JsonSerializerOptions options)
{
writer.WriteNumberValue(value.Value);
}
}
}
public class TestModel {
[BsonId]
public ObjectId Id { get; set; }
public DiscordUserId UserId { get; set; }
public string Name { get; set; }
}
public class TestModelWithDictionary {
[BsonId]
public ObjectId Id { get; set; }
public Dictionary<DiscordUserId, List<TestModel>> Dictionary { get; set; }
}
Mapping
BsonMapper.RegisterType(id => id.Value, bson => new DiscordUserId(bson.AsInt64));
Tests
[Fact]
public void CanReadIdentityDict() {
//Arrange
using var db = _dbManager.GetDatabase();
var model = new TestModel() {
Name = "MyTestName",
UserId = new DiscordUserId(513512)
};
var model2 = new TestModel() {
Name = "MyTestName2",
UserId = new DiscordUserId(5139512)
};
var model3 = new TestModel() {
Name = "MyTestName3",
UserId = new DiscordUserId(5139512)
};
var dict = new Dictionary<DiscordUserId, List<TestModel>>() {
{ model.UserId, new(){model} },
{ model2.UserId, new(){model2, model3} }
};
var toWrite = new TestModelWithDictionary() {
Dictionary = dict
};
//Act
var coll = db.GetCollection<TestModelWithDictionary>("Dicts");
var written = coll.Insert(toWrite);
var read = coll.FindAll().FirstOrDefault();
//Assert
read.Should().NotBeNull();
read.Should().BeEquivalentTo(model, opts => opts.Excluding(x=> x.Id));
}
Expected behavior
The dictionary should be able to be recreated, especially since there is a mapping tool.
Screenshots/Stacktrace
System.InvalidCastException: Invalid cast from 'System.String' to 'DiscordBot.Common.Identities.DiscordUserId'.
System.InvalidCastException
Invalid cast from 'System.String' to 'DiscordBot.Common.Identities.DiscordUserId'.
at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at LiteDB.BsonMapper.DeserializeDictionary(Type K, Type T, IDictionary dict, BsonDocument value)
at LiteDB.BsonMapper.Deserialize(Type type, BsonValue value)
at LiteDB.BsonMapper.DeserializeObject(EntityMapper entity, Object obj, BsonDocument value)
at LiteDB.BsonMapper.Deserialize(Type type, BsonValue value)
at LiteDB.LiteQueryable`1.<ToEnumerable>b__27_2(BsonDocument x)
at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
at DiscordBot.ServicesTests.Data.IdentityTests.CanReadIdentityDict()
Additional context
This method seems to be the 'killer' and should reference the correct mapping functions
Version Which LiteDB version/OS/.NET framework version are you using. (REQUIRED)
Describe the bug When having a dictionary with a custom key type (for example a strongly typed long) it will be unable to cast/convert into the corrext type, even when you have a mapping function for said custom key.
Code to Reproduce
Models
Mapping
Tests
Expected behavior The dictionary should be able to be recreated, especially since there is a mapping tool.
Screenshots/Stacktrace
Additional context This method seems to be the 'killer' and should reference the correct mapping functions