数据库
首页 > 数据库> > 插入数组到MongoDB的子集合中将省略_t Discriminator

插入数组到MongoDB的子集合中将省略_t Discriminator

作者:互联网

给定这些类:

public class Parent
{
    public IEnumerable<IChild> Children { get; set; }
}

public interface IChild { }

public class Child : IChild { }

将Children属性作为一个数组插入,如下所示:

using MongoDB.Driver;
using System.Collections.Generic;

namespace TestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var db = new MongoClient().GetDatabase("Test");
            var collection = db.GetCollection<Parent>("Parent");
            collection.InsertOne(new Parent { Children = new[] { new Child() } });
        }
    }
}

数据库中缺少_t鉴别符:

{
    "_id":"5bf6aef6c0beccc414b70d45",
    "Child":[{}]
}

如果我改用列表:

collection.InsertOne(new Parent { Children = new List<IChild> { new Child() } });

_t鉴别符设置正确:

{
    "_id":"5bf6b074c0beccc414b70dc2",
    "Children":[{"_t":"Child"}]
}

这似乎是一个错误,或者至少是非常不直观的行为.

附加信息:
该行为是一个问题,因为缺少的_t Discriminator在反序列化对象时会导致异常:

System.FormatException: ‘An error occurred while deserializing the Children property of class TestConsoleApp.Parent: Unable to determine actual type of object to deserialize for interface type TestConsoleApp.IChild.’

解决方法:

造成此问题的原因是mongo没有发现IChild接口的实现类.换句话说,mongo驱动程序不知道必须使用Child类创建IChild实现.那就是为什么要添加_t Discriminator.

要解决此问题,您可以指定隐式序列化.

public class Parent
{
[BsonSerializer(typeof(ImpliedImplementationInterfaceSerializer<IEnumerable<IChild>, IEnumerable<Child>>))]
    public IEnumerable<IChild> Children { get; set; }
}

使用此属性,它将不会创建_t歧视,但会使用Child类进行反序列化.

如果您想在动态实例上强制使用鉴别符,则可以使用

[BsonDiscriminator(Required = true)]
    public class Child : IChild { }

请注意,应将此标头添加到您需要强制创建标识符的所有类中.

标签:mongodb,mongodb-net-driver,c,net
来源: https://codeday.me/bug/20191108/2007699.html