MongoDB的LINQ提供程序的奇怪行为领域所谓的“身份证”(Strange behavior o

2019-07-05 04:13发布

这里有一个JSON文件,其中蒙戈LINQ提供程序失败:

{"results":
     {"text":"@twitterapi  http://tinyurl.com/ctrefg",
     "to_user_id":396524,
     "to_user":"TwitterAPI",
     "from_user":"jkoum",
     "metadata":
     {
      "result_type":"popular",
      "recent_retweets": 109
     },
     "id":1478555574, 
     "from_user_id":1833773,
     "iso_language_code":"nl",
     "source":"<a href=\"http://twitter.com/\">twitter<\/a>",
     "profile_image_url":"http://s3.amazonaws.com/twitter_production/profile_images/118412707/2522215727_a5f07da155_b_normal.jpg",
     "created_at":"Wed, 08 Apr 2009 19:22:10 +0000",
     "since_id":0,
     "max_id":1480307926,
     "refresh_url":"?since_id=1480307926&q=%40twitterapi",
     "results_per_page":15,
     "next_page":"?page=2&max_id=1480307926&q=%40twitterapi",
     "completed_in":0.031704,
     "page":1,
     "query":"%40twitterapi"}
}

注意一个“id”字段。 以下是相关的C#实体的定义:

class Twitter
{
    [BsonId]
    public ObjectId Id { get; set; }
    public Result results { get; set; }
}

private class Result
{
    public string text { get; set; }
    public int to_user_id { get; set; }
    public string to_user { get; set; }
    public string from_user { get; set; }
    public Metadata metadata { get; set; }
    public int id { get; set; }
    public int from_user_id { get; set; }
    public string iso_language_code { get; set; }
    public string source { get; set; }
    public string profile_image_url { get; set; }
    public string created_at { get; set; }
    public int since_id { get; set; }
    public int max_id { get; set; }
    public string refresh_url { get; set; }
    public int results_per_page { get; set; }
    public string next_page { get; set; }
    public double completed_in { get; set; }
    public int page { get; set; }
    public string query { get; set; }
}

class Metadata
{
    public string result_type { get; set; }
    public int recent_retweets { get; set; }
}

如果我创建了一个“推特”收集并保存上述文件,然后当我使用蒙戈LINQ提供查询,它抛出一个异常FileFormatException:“元素‘ID’不匹配类Mongo.Context.Tests的任何字段或属性。 NativeTests +结果”

然而,有两种可供选择的解决方法来解决这个问题:

  1. 结果重命名“ID”字段,如双方在JSON文档和Result类“IDD”。 然后,LINQ查询工作。
  2. 保持“ID”字段,但除了一个字段“ID”添加到结果类以及属性[BsonId]对它进行标记。 现在的结果类同时包含“ID”和“ID”字段,但查询的工作!

我使用Mongo的API来查询集合,一切工作正常,所以我想这一定是在MongoDB的LINQ提供程序的错误。 “ID”嵌套JSON元素不应该保留的工作,应该吗?

更新 :这是一个原生API查询执行的结果:

> db.Twitter.find().limit(1);

{ "_id" : ObjectId("50c9d3a4870f4f17e049332b"),
 "results" : { 
    "text" : "@twitterapi  http://tinyurl.com/ctrefg", 
    "to_user_id" : 396524, 
    "to_user" : "TwitterAPI", 
    "from_user" : "jkoum", 
    "metadata" : { "result_type" : "popular", "recent_retweets" : 109 }, 
    "id" : 1478555574, 
    "from_user_id" : 1833773, "
    iso_language_code" : "nl", 
    "source" : "<a href=\"http://twitter.com/\">twitter</a>", 
    "profile_image_url" : "http://s3.amazonaws.com/twitter_production/profile_images/118412707/2522215727_a5f07da155_b_normal.jpg", 
    "created_at" : "Wed, 08 Apr 2009 19:22:10 +0000", 
    "since_id" : 0, 
    "max_id" : 1480307926, 
    "refresh_url" : "?since_id=1480307926&q=%40twitterapi", "results_per_page" : 15,    "next_page" : "?page=2&max_id=1480307926&q=%40twitterapi", 
    "completed_in" : 0.031704, 
    "page" : 1, 
    "query" : "%40twitterapi" 
    } 
}

Answer 1:

MongoDB的要求存储在数据库中的每个文件有一个字段(在根级别)称为“_id”。

C#的驱动程序假定,在你的类名为“ID”,“ID”或“_id”任何领域是指被映射到特殊的“_id”字段。 这是一个约定,一个是不能修改的。 C#的司机不知道,你的结果类是注定不会被用作集的根文件,所以它找到你的“ID”字段和地图数据库中的“_id”。

您可以覆盖的方法之一是改变你的类中的字段的名称(如你发现)。 那么,什么你也可以做的是使用[BsonElement]属性映射你的C#字段名(如“IDD”)数据库中的实际使用任何名称(例如,“ID”)。 例如:

public class Result
{
    [BsonElement("id")]
    public int idd; // matches "id" in the database
    // other fields
}

另一种方法是重写发现一类的“ID”成员压制你的结果类C#驱动程序的默认行为公约。 您可以通过注册一个新的ConventionProfile你的结果类做到这一点。 例如:

var noIdConventions= new ConventionProfile();
noIdConventions.SetIdMemberConvention(new NamedIdMemberConvention()); // no names
BsonClassMap.RegisterConventions(noIdConventions, t => t == typeof(Result));

你必须确保做到这一点在你的程序非常早,你的结果类被映射之前。



Answer 2:

问题是你的POCO不符合您的JSON

Twitter类有一个ID和一个类中调用结果
然而,你的JSON只是有结果。 这就是问题所在。

因此,在现实中,你绕过Twitter类,只是创建的实例Result

你的JSON应该是这个样子:

{
  _id: ObjectId("50c9c8f3e0ae76405f7d2b5e"), 
  "results": { 
     "text":"@twitterapi  http://tinyurl.com/ctrefg",
     "to_user_id":396524,
     "to_user":"TwitterAPI",
     "from_user":"jkoum",
     "metadata":
     {
      "result_type":"popular",
      "recent_retweets": 109
     },
     "id":1478555574, 
     "from_user_id":1833773,
     "iso_language_code":"nl",
     "source":"<a href=\"http://twitter.com/\">twitter<\/a>",
     "profile_image_url":"http://s3.amazonaws.com/twitter_production/profile_images/118412707/2522215727_a5f07da155_b_normal.jpg",
     "created_at":"Wed, 08 Apr 2009 19:22:10 +0000",
     "since_id":0,
     "max_id":1480307926,
     "refresh_url":"?since_id=1480307926&q=%40twitterapi",
     "results_per_page":15,
     "next_page":"?page=2&max_id=1480307926&q=%40twitterapi",
     "completed_in":0.031704,
     "page":1,
     "query":"%40twitterapi"}
    }
}

编辑

你的results实际上是一个嵌入式文件(在目前的POCO模型的情况下),所以你也应该纪念Result.ID与[BsonId]



文章来源: Strange behavior of MongoDB LINQ provider for fields called “id”