我有一个函数,它返回一个tweets列表。列表中的每个元素都有大量的数据,tweet的文本、位置、用户信息(如果是转发的话)、时间、转发信息、图片链接,还有更多的数据,相互之间的数据列表。
我正在使用linq2twitter包,它为我提供了一个名为status的对象,这就是我所说的tweet。
此代码从我的函数获取数据:var container = await DoPagedSearchAsync(context, this);
我的数据库看起来是这样的:
public class TweetContext : DbContext
{
public DbSet<Status> Tweets { get; set; }
}
我试图用以下代码添加数据:
using (var vontex = new TweetContext())
{
vontex.Tweets.AddRange(container);
vontex.SaveChanges();
}
下面是我在运行时在该行得到的错误列表:
vontex.Tweets.AddRange(container);
:在模型生成期间检测到一个或多个验证错误:
dataacquirer.models.status::EntityType“status”未定义键。定义此EntityType的键。
dataacquirer.models.coordinate::EntityType“coordinate”未定义键。定义此EntityType的键。
DataAcquirer.Models.Entities::EntityType“Entities”未定义键。>定义此EntityType的键。
DataAcquirer.Models.HashTagEntity::EntityType“HashTagEntity”未定义键。定义此EntityType的键。
dataacquirer.models.photoSize::EntityType“photoSize”未定义键。定义此EntityType的键。
dataacquirer.models.videoinfo::entitytype“videoinfo”未定义密钥。定义此EntityType的键。
dataacquirer.models.variant::EntityType“variant”未定义键。定义此EntityType的键。
DataAcquirer.Models.SymbolEntity::EntityType“SymbolEntity”未定义键。定义此EntityType的键。
DataAcquirer.Models.UrlEntity::EntityType“UrlEntity”未定义键。定义此EntityType的键。
dataacquirer.models.userInspectiveEntity::EntityType“userInspectiveEntity”未定义键。定义此EntityType的键。
dataacquirer.models.geometry::EntityType“geometry”未定义键。定义此EntityType的键。
dataacquirer.models.user::EntityType“user”未定义键。定义此EntityType的键。
DataAcquirer.Models.BannerSize::EntityType“BannerSize”未定义键。定义此EntityType的键。
dataacquirer.models.category::entitytype“category”未定义键。定义此EntityType的键。
tweets:entitytype:entityset“tweets”基于未定义键的“status”类型。
坐标:EntityType:EntitySet“坐标”基于未定义键的“坐标”类型。
实体:EntityType:EntitySet“Entities”基于未定义键的“Entities”类型。
HashTagEntities:EntityType:EntitySet“HashTagEntities”基于未定义键的“HashTagEntity”类型。
photoSize:EntityType:EntitySet“photoSize”基于未定义键的“photoSize”类型。
videoinfoes:entitytype:entityset“videoinfoes”基于未定义键的“videoinfo”类型。
variants:entitytype:entityset“variants”基于未定义键的类型“variant”。
symbolEntities:EntityType:EntitySet“symbolEntities”基于未定义键的“symbolEntity”类型。
urlEntities:EntityType:EntitySet“urlEntities”基于未定义键的类型“urlEntity”。
userInspectionEntities:EntityType:EntitySet“userInspectionEntities”基于未定义键的“userInspectionEntity”类型。
geometries:entitytype:entityset“geometries”基于未定义键的“geometry”类型。
users:entitytype:entityset“users”基于未定义键的“user”类型。
bannersizes:entitytype:entityset“bannersizes”基于未定义键的类型“bannersize”。
类别:EntityType:EntitySet“Categories”基于未定义键的“Category”类型。
这个类看起来如下所示:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using LitJson;
namespace LinqToTwitter
{
[XmlType(Namespace = "LinqToTwitter")]
public class Status
{
public Status();
public Status(JsonData status);
public Annotation Annotation { get; set; }
public List<Contributor> Contributors { get; set; }
public Coordinate Coordinates { get; set; }
public int Count { get; set; }
public DateTime CreatedAt { get; set; }
public ulong CurrentUserRetweet { get; set; }
public long Cursor { get; set; }
public Cursors CursorMovement { get; set; }
public EmbeddedStatus EmbeddedStatus { get; set; }
public Entities Entities { get; set; }
public bool ExcludeReplies { get; set; }
public Entities ExtendedEntities { get; set; }
public int? FavoriteCount { get; set; }
public bool Favorited { get; set; }
public FilterLevel FilterLevel { get; set; }
public ulong ID { get; set; }
public bool IncludeContributorDetails { get; set; }
public bool IncludeEntities { get; set; }
public bool IncludeMyRetweet { get; set; }
public bool IncludeRetweets { get; set; }
public bool IncludeUserEntities { get; set; }
public string InReplyToScreenName { get; set; }
public ulong InReplyToStatusID { get; set; }
public ulong InReplyToUserID { get; set; }
public string Lang { get; set; }
public bool Map { get; set; }
public ulong MaxID { get; set; }
public StatusMetaData MetaData { get; set; }
public EmbeddedStatusAlignment OEmbedAlign { get; set; }
public bool OEmbedHideMedia { get; set; }
public bool OEmbedHideThread { get; set; }
public string OEmbedLanguage { get; set; }
public int OEmbedMaxWidth { get; set; }
public bool OEmbedOmitScript { get; set; }
public string OEmbedRelated { get; set; }
public string OEmbedUrl { get; set; }
public Place Place { get; set; }
public bool PossiblySensitive { get; set; }
public Status QuotedStatus { get; set; }
public ulong QuotedStatusID { get; set; }
public int RetweetCount { get; set; }
public bool Retweeted { get; set; }
public Status RetweetedStatus { get; set; }
[XmlIgnore]
public Dictionary<string, string> Scopes { get; set; }
public string ScreenName { get; set; }
public ulong SinceID { get; set; }
public string Source { get; set; }
public ulong StatusID { get; set; }
public string Text { get; set; }
public bool TrimUser { get; set; }
public bool Truncated { get; set; }
public string TweetIDs { get; set; }
[XmlIgnore]
public StatusType Type { get; set; }
public User User { get; set; }
public ulong UserID { get; set; }
public List<ulong> Users { get; set; }
public bool WithheldCopyright { get; set; }
public List<string> WithheldInCountries { get; set; }
public string WithheldScope { get; set; }
}
}
无法编辑上述模型。它附带了linq2twitter包。
最佳答案
这种方法行不通。twitter api返回的对象是分层的,而不是关系的。例如,以下是linq to twitter消费的一个片段:
{
"retweeted":false,
"in_reply_to_screen_name":null,
"possibly_sensitive":false,
"retweeted_status":{
"retweeted":false,
...,
"user":{
"id":41754227,
...
},
...
},
"contributors":null,
"coordinates":{
"type":"Point",
"coordinates":[
-122.40060,
37.78215
]
},
"place":null,
"user":{
"id":15411837,
...
},
"retweet_count":393,
...
}
linq to twitter将其转换为
Tweet
类型,Tweet
类型有一些习惯用法,使构建linqwhere
子句更加容易。Tweet
仍然是分层的。要了解
Tweet
的层次结构,请注意上面的json在Tweet
下有更复杂的对象,例如retweeted_status
(linq to twitter中的retweedstatus),它是Tweet
的Tweet
类型属性,而user
是User
的Tweet
类型属性。在RetweetedStatus
和User
中是更复杂的对象。对于您看到的问题,请注意
coordinates
属性。它没有ID
的值,因为它主要是一个值。因为它的语义,也许它可以被更好地建模为一个struct,也许这是我在这里要做的事情之一,但事实是,它没有,也永远不会有一个ID
。如果查看错误消息中的项目列表,您将看到大多数错误是针对值类型对象的,如coordinates
。一种方法是不要在关系模型中持久化,而是寻找一个能够满足您需求的nosql选项。比如MongoDB或者微软的新CosmosDB——还有无数的选择。我在自己的代码中采用了这种方法,因为虽然现在twitter api更加严格,但它过去的变化是不可预测的。也就是说,现在一种关系型的方法可能是可行的。在这种方法中,您可以从twitter读取原始内容,如下所示:
string jsonResults = vontex.RawResults;
然后,您可以使用json.net提取单个tweets。
下面是我将如何使用关系方法:
使用Automapper。学习这个工具所需的少量时间将不仅在这个项目中,而且在将来产生许多好处。
创建自己的适合关系持久化的对象。
使用关系引用将转发状态引用回原始tweet。
创建一个用户表并创建从
Tweet
到Tweet
的引用。对于所有值类型对象,有两个选项:
a.如果是一个单独的值,比如
User
,则将其展平到coordinates
。b.如果是一个多值,比如
Tweet
,则创建一个单独的表,其中实体有自己的伪键,并引用entities
。我知道你想看看密码。然而,这是一个巨大的工作和编写代码将相当于我为您编写整个数据访问层,这将是不合理的论坛回答。我仍然会走NoSQL路线,除非有一个很难去关系。希望这有帮助。