C# 元素';id';与嵌套类不匹配任何错误字段或属性

C# 元素';id';与嵌套类不匹配任何错误字段或属性,c#,mongodb,mongodb-.net-driver,C#,Mongodb,Mongodb .net Driver,我有以下mongodb文档模式 { "_id" : ObjectId("5c9d34ff781318afb9e8ab43"), "name" : "Name", "slug" : "slug", "services" : { "subservice" : { "id" : NumberInt(37030) } } } 然后我将我的类定义为 public class MainModel {

我有以下mongodb文档模式

{ 
    "_id" : ObjectId("5c9d34ff781318afb9e8ab43"), 
    "name" : "Name", 
    "slug" : "slug",
    "services" : {
        "subservice" : {
            "id" : NumberInt(37030)
        }
    }
}
然后我将我的类定义为

public class MainModel
{
    public ObjectId Id { get; set; }

    [BsonElement("name")]
    public string Name { get; set; }

    [BsonElement("slug")]
    public string Slug { get; set; }

    [BsonElement("services")]
    public ServicesDef Services { get; set; }

    public class ServicesDef 
    {
        [BsonElement("subservice")]
        public SubServiceDef SubService{ get; set; }

        public class SubServiceDef 
        {
            [BsonElement("id")]
            public int Id { get; set; }
        }
    }
}
但不知何故,当我查询文档时

var result = await Repository.FindAsync(x => x.Slug == slug);
该services.subservice.id未正确注册并获取

元素“id”与SubServiceDef类的任何字段或属性都不匹配

被困在这里寻求建议


我想我也有同样的问题,但似乎还有解决办法。

长话短说:这都是关于约定的。MongoDB.NET驱动程序公开静态类
ConventionRegistry
,允许您注册自己的约定(更多)。此外,还有两个“内置”约定
\uuuuuuu默认值\uuuuuu
\uuuu属性\uuuuu
。深入挖掘(驱动程序),您会发现它记录了一个非常有趣的约定:

new NamedIdMemberConvention(new [] { "Id", "id", "_id" })
这意味着
id
成员将被视为常规BSON\u id元素

如何解决这个问题

您可以摆脱默认约定

ConventionRegistry.Remove("__defaults__");
但是,您会自动放弃所有其他驱动程序约定,这是相当危险的。或者,您可以创建一个始终为空的假属性:

public class SubServiceDef
{
    [BsonElement("id")]
    public int Id { get; set; }

    [BsonId]
    public ObjectId FakeId { get; set; }
}
或者您可以只使用
BsonNoId
属性

指定类的IdMember应为null


因此,约定将您的
id
设置为类映射中的IdMember,但在后处理过程中,此属性将强制IdMember为null,并且您的类将成功地反序列化。MongoDB.NET驱动程序公开静态类
ConventionRegistry
,允许您注册自己的约定(更多)。此外,还有两个“内置”约定
\uuuuuuu默认值\uuuuuu
\uuuu属性\uuuuu
。深入挖掘(驱动程序),您会发现它记录了一个非常有趣的约定:

new NamedIdMemberConvention(new [] { "Id", "id", "_id" })
这意味着
id
成员将被视为常规BSON\u id元素

如何解决这个问题

您可以摆脱默认约定

ConventionRegistry.Remove("__defaults__");
但是,您会自动放弃所有其他驱动程序约定,这是相当危险的。或者,您可以创建一个始终为空的假属性:

public class SubServiceDef
{
    [BsonElement("id")]
    public int Id { get; set; }

    [BsonId]
    public ObjectId FakeId { get; set; }
}
或者您可以只使用
BsonNoId
属性

指定类的IdMember应为null


因此,约定将您的
id
设置为类映射中的IdMember,但在后处理过程中,此属性将强制IdMember为null,并且您的类将成功反序列化

我喜欢@mickl给出的答案。我遇到的问题是无法更新模型和添加属性。我还需要反序列化后的原始
Id
s和not
null
s

我尝试了
BsonClassMap
,但是我有太多的子模型需要更新

所以,我最终用你的想法删除了默认约定

public class MongoDbDefaultConventionPack : IConventionPack
{
    // private static fields
    private static readonly IConventionPack __defaultConventionPack = new MongoDbDefaultConventionPack();

    // private fields
    private readonly IEnumerable<IConvention> _conventions;

    // constructors
    /// <summary>
    /// Initializes a new instance of the <see cref="MongoDbDefaultConventionPack" /> class.
    /// </summary>
    private MongoDbDefaultConventionPack()
    {
        _conventions = new List<IConvention>
        {
            new ReadWriteMemberFinderConvention(),
            // new NamedIdMemberConvention(new [] { "Id", "id", "_id" }), changed to:
            new NamedIdMemberConvention(),
            new NamedExtraElementsMemberConvention(new [] { "ExtraElements" }),
            // new IgnoreExtraElementsConvention(false), changed to:
            new IgnoreExtraElementsConvention(true),
            new ImmutableTypeClassMapConvention(),
            new NamedParameterCreatorMapConvention(),
            new StringObjectIdIdGeneratorConvention(), // should be before LookupIdGeneratorConvention
            new LookupIdGeneratorConvention()
        };
    }

    // public static properties
    /// <summary>
    /// Gets the instance.
    /// </summary>
    public static IConventionPack Instance
    {
        get { return __defaultConventionPack; }
    }

    // public properties
    /// <summary>
    /// Gets the conventions.
    /// </summary>
    public IEnumerable<IConvention> Conventions
    {
        get { return _conventions; }
    }
}

作为默认约定,在我的情况下非常有效。没有例外。原始ID可用

我喜欢@mickl的答案。我遇到的问题是无法更新模型和添加属性。我还需要反序列化后的原始
Id
s和not
null
s

我尝试了
BsonClassMap
,但是我有太多的子模型需要更新

所以,我最终用你的想法删除了默认约定

public class MongoDbDefaultConventionPack : IConventionPack
{
    // private static fields
    private static readonly IConventionPack __defaultConventionPack = new MongoDbDefaultConventionPack();

    // private fields
    private readonly IEnumerable<IConvention> _conventions;

    // constructors
    /// <summary>
    /// Initializes a new instance of the <see cref="MongoDbDefaultConventionPack" /> class.
    /// </summary>
    private MongoDbDefaultConventionPack()
    {
        _conventions = new List<IConvention>
        {
            new ReadWriteMemberFinderConvention(),
            // new NamedIdMemberConvention(new [] { "Id", "id", "_id" }), changed to:
            new NamedIdMemberConvention(),
            new NamedExtraElementsMemberConvention(new [] { "ExtraElements" }),
            // new IgnoreExtraElementsConvention(false), changed to:
            new IgnoreExtraElementsConvention(true),
            new ImmutableTypeClassMapConvention(),
            new NamedParameterCreatorMapConvention(),
            new StringObjectIdIdGeneratorConvention(), // should be before LookupIdGeneratorConvention
            new LookupIdGeneratorConvention()
        };
    }

    // public static properties
    /// <summary>
    /// Gets the instance.
    /// </summary>
    public static IConventionPack Instance
    {
        get { return __defaultConventionPack; }
    }

    // public properties
    /// <summary>
    /// Gets the conventions.
    /// </summary>
    public IEnumerable<IConvention> Conventions
    {
        get { return _conventions; }
    }
}

作为默认约定,在我的情况下非常有效。没有例外。原始ID可用

@Simons0n无法想象这会是一个生死攸关的问题,但听到这个消息很高兴,请保持安全@西蒙森无法想象这会是一个生死攸关的问题,但很高兴听到这个消息,请保持安全!