对于名为"id"的字段,MongoDB LINQ提供程序的奇怪行为是: [英] Strange behavior of MongoDB LINQ provider for fields called "id"
问题描述
这是Mongo LINQ提供程序失败的JSON文档:
Here's a JSON document where Mongo LINQ provider fails:
{"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#实体定义:
Note an "id" field. Here are related C# entity definitions:
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; }
}
如果创建"Twitter"集合并保存上面的文档,则当我使用Mongo LINQ提供程序对其进行查询时,它将引发FileFormatException异常: 元素'id'与Mongo.Context.Tests.NativeTests + Result类的任何字段或属性都不匹配"
If I create a "Twitter" collection and save the document above, then when I query it using Mongo LINQ provider, it throws a FileFormatException exception: "Element 'id' does not match any field or property of class Mongo.Context.Tests.NativeTests+Result"
但是,有两种替代方法可以解决此问题:
However there are two alternative workarounds to fix this problem:
- 重命名结果"id"字段,例如JSON文档和Result类中的"idd".然后LINQ查询开始工作.
- 保留"id"字段,但还要在Result类中添加字段"Id",并使用属性[BsonId]对其进行标记.现在Result类同时包含"Id"和"id"字段,但查询有效!
我使用Mongo API查询集合,一切正常,所以我想这一定是MongoDB LINQ提供程序中的错误.嵌套JSON元素中的"id"不应该是保留的作品,对吗?
I use Mongo API to query the collection, everything works fine, so I guess this must be a bug in a MongoDB LINQ provider. "id" in a nested JSON element should not be a reserved work, should it?
更新:这是本机API查询执行的结果:
UPDATE: Here's the result of a native API query execution:
> 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"
}
}
推荐答案
MongoDB要求存储在数据库中的每个文档都有一个名为"_id"的字段(在根级别).
MongoDB requires that every document stored in the database have a field (at the root level) called "_id".
C#驱动程序假定您的类中称为"Id","id"或"_id"的任何字段都应映射到特殊的"_id"字段.这是一个约定,可以重写. C#驱动程序不知道您的Result类不是要用作集合的根文档,因此它会找到您的"id"字段并将其映射到数据库中的"_id".
The C# driver assumes that any field in your class called "Id", "id" or "_id" is meant to be mapped to the special "_id" field. This is a convention, one that can be overridden. The C# driver doesn't know that your Result class isn't meant to be used as the root document of a collection, so it finds your "id" field and maps it to "_id" in the database.
您可以重写此方法的一种方法是更改类中字段的名称(如您所发现的).然后,您还可以使用[BsonElement]属性将C#字段名称(例如"idd")映射到数据库中实际使用的任何名称(例如"id").例如:
One way you can override this is to change the name of the field in your class (as you discovered). What you can then also do is use the [BsonElement] attribute to map your C# field name (e.g. "idd") to whatever name is actually being used in the database (e.g. "id"). For example:
public class Result
{
[BsonElement("id")]
public int idd; // matches "id" in the database
// other fields
}
另一种替代方法是覆盖查找类的"Id"成员的约定,以禁止Result类的C#驱动程序的默认行为.您可以通过为Result类注册一个新的ConventionProfile来实现.例如:
Another alternative is to override the convention that finds the "Id" member of a class to suppress the default behavior of the C# driver for your Result class. You can do this by registering a new ConventionProfile for your Result class. For example:
var noIdConventions= new ConventionProfile();
noIdConventions.SetIdMemberConvention(new NamedIdMemberConvention()); // no names
BsonClassMap.RegisterConventions(noIdConventions, t => t == typeof(Result));
在确定Result类映射之前,您必须确保在程序的早期执行此操作.
You must be sure to do this very early in your program, before your Result class gets mapped.
这篇关于对于名为"id"的字段,MongoDB LINQ提供程序的奇怪行为是:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!