提问人:Asbah Qadeer 提问时间:8/16/2017 最后编辑:Joe MayoAsbah Qadeer 更新时间:8/17/2017 访问量:323
实体框架在添加没有 ID 的数据时引发错误
Entity Framework throwing an error when adding data without IDs
问:
我有一个函数,它返回推文列表。该列表中的每个元素都有很多数据,推文的文本、位置、用户信息(如果是转发)、时间、转发信息、图片链接,以及更多数据,彼此之间的数据列表。
我正在使用 Linq2Twitter 包,它为我提供了一个名为 Status 的对象,这就是我所说的推文。
此代码从我的函数中获取数据:var container = await DoPagedSearchAsync(context, this);
我的 DBSet 如下所示:
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.UserMentionEntity::EntityType 'UserMentionEntity' 未定义键。定义此 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 的键。 推文:EntityType:EntitySet“推文”基于未定义键的类型“Status”。 坐标:EntityType:EntitySet“坐标”基于未定义键的“坐标”类型。 实体:EntityType:EntitySet“实体”基于未定义键的“实体”类型。 HashTagEntities:EntityType:EntitySet“HashTagEntities”基于未定义键的类型“HashTagEntity”。 PhotoSizes:EntityType:EntitySet“PhotoSizes”基于未定义键的“PhotoSize”类型。 VideoInfoes:EntityType:EntitySet“VideoInfoes”基于未定义键的类型“VideoInfo”。 变体:EntityType:EntitySet“Variants”基于未定义键的类型“Variant”。 SymbolEntities:EntityType:EntitySet“SymbolEntities”基于未定义键的类型“SymbolEntity”。 UrlEntities:EntityType:EntitySet“UrlEntities”基于未定义键的类型“UrlEntity”。 UserMentionEntities:EntityType:EntitySet“UserMentionEntities”基于未定义键的类型“UserMentionEntity”。 Geometries: EntityType: EntitySet 'Geometries' 基于未定义键的 'Geometry' 类型。 用户:EntityType:EntitySet“Users”基于未定义键的类型“User”。 BannerSizes:EntityType:EntitySet“BannerSizes”基于未定义键的“BannerSize”类型。 类别:EntityType:EntitySet“类别”基于未定义键的类型“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 包。
答:
如果您计划手动创建 ID,则可以从 Status 继承并添加如下内容:
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
或使用注释中所述的 Key 属性 (http://www.entityframeworktutorial.net/code-first/key-dataannotations-attribute-in-code-first.aspx)
[Key]
public Guid Id { get; set; }
我希望它有所帮助。
评论
您是否查看过 System.Data.Entity.ModelConfiguration.EntityTypeConfiguration
您可以创建地图:
public class StatusMap : EntityTypeConfiguration<Status>
{
public StatusMap()
{
ToTable("StatusTable")
.HasKey(p => p.ID);
}
}
然后,在上下文中,您可以添加:
protected override void OnModelCreating([NotNull] DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new StatusMap());
}
这种方法是行不通的。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 将其转换为一种类型,并且该类型具有一些习惯用语,以便更轻松地生成 LINQ 子句。仍然是分层的。Tweet
Tweet
where
Tweet
要了解 的层次结构,请注意上面的 JSON 在 下有更复杂的对象,例如 (LINQ to Twitter 中的 RetweetedStatus),它是 的 类型属性,也是 的类型属性。内部和是更复杂的对象。Tweet
Tweet
retweeted_status
Tweet
Tweet
user
User
Tweet
RetweetedStatus
User
对于您看到的问题,请注意属性。它没有,因为它主要是一个值。也许它更适合建模为语义结构,也许这是我在这里的收获之一,但事实是它没有,也永远不会有一个.如果浏览错误消息中的项列表,您将看到大多数错误都针对值类型对象,例如 .coordinates
ID
ID
coordinates
一种方法是不保留在关系模型中,而是寻找满足您需求的 NoSQL 选项。例如MongoDB或Microsoft的新CosmosDB - 还有无数的选择。我在自己的代码中采用了这种方法,因为虽然现在的 Twitter API 更加严格,但它过去的变化是不可预测的。也就是说,如今关系方法可能是可行的。在这种方法中,你可以像这样从Twitter上读取原始内容:
string jsonResults = vontex.RawResults;
然后,您可以使用 Json.NET 提取单个推文。
以下是我将使用关系方法执行的操作:
- 使用自动映射器。学习这个工具所花费的少量时间不仅会给这个项目带来很多好处,而且会在未来带来很多好处。
- 创建适合关系持久性的自己的对象。
Tweet
- 使用关系引用将转发的状态引用回原始推文。
- 创建一个 User 表,并创建从 到 .
Tweet
User
- 对于所有值类型对象,您有两个选项:
一个。如果它是单个值,例如 ,则将其展平为 .
b.如果它是多值,例如 ,则创建一个单独的表,其中实体具有自己的伪键并引用回 .
coordinates
Tweet
entities
Tweet
我知道你想看代码。然而,这是一项艰巨的工作,编写代码相当于我为你编写整个数据访问层,这对于论坛的答案来说是不合理的。我仍然会走NoSQL路线,除非有硬性要求去关系。希望这会有所帮助。
评论