实体框架在添加没有ID的数据时抛出错误

时间:2017-08-16 09:03:06

标签: c# database entity-framework twitter linq-to-twitter

我有一个返回推文列表的函数。该列表中的每个元素都有大量数据,推文的文本,位置,用户信息,如果是转推,它的时间,转发信息,图片链接和更多数据,彼此之间的数据列表列表。

我正在使用Linq2Twitter包,它为我提供了一个名为Status的对象,这就是我所说的Tweet。

此代码从我的函数中获取数据: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'没有定义键。 &gt;定义此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'RisualEntity'没有定义键。定义此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'BandateSize'没有定义键。定义此EntityType的键。   DataAcquirer.Models.Category :: EntityType'Categage'没有定义键。定义此EntityType的键。   推文:EntityType:EntitySet'推文'基于类型'状态',没有定义键。   坐标: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'RisualEntities'基于没有定义键的类型'SymbolEntity'。   UrlEntities:EntityType:EntitySet'UrlEntities'基于类型'UrlEntity',没有定义键。   UserMentionEntities:EntityType:EntitySet'UserMentionEntities'基于没有定义键的'UserMentionEntity'类型。   几何:EntityType:EntitySet'Geometries'基于没有定义键的'Geometry'类型。   用户:EntityType:EntitySet'Users'基于没有定义键的'User'类型。   BannerSizes:EntityType:EntitySet'BrainSizes'基于没有定义键的类型'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软件包。

3 个答案:

答案 0 :(得分:1)

这种方法不起作用。 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类型有一些习惯用语,以便更容易构建LINQ where子句。 Tweet仍然是分层的。

要理解Tweet的层次结构,请注意上面的JSON在Tweet下面有更复杂的对象,例如retweeted_status(在LINQ to Twitter中转发的状态),这是Tweet的{​​{1}}类型属性,以及Tweet的{​​{1}}类型属性user。在UserTweet内是更复杂的对象。

针对您所看到的问题,请注意RetweetedStatus属性。它没有User,因为它主要是一个值。也许它本来可以更好地建模为它的语义结构,也许这是我在这里的一个外卖,但事实是它没有,也永远不会有coordinates。如果您浏览错误消息中的项目列表,则会发现大多数错误都适用于ID等值类型对象。

一种方法是不要在关系模型中持久存在并寻找满足您需求的NoSQL选项。例如MongoDB或微软的新CosmosDB - 有无数的选择。我在自己的代码中采用了这种方法,因为虽然Twitter API现在更加严谨,但它过去常常无法改变。也就是说,近来关系方法可能是可行的。在这种方法中,您可以从Twitter读取原始内容,如下所示:

ID

然后你可以使用Json.NET推出个人推文。

这是我用关系方法做的事情:

  1. 使用Automapper。学习这个工具需要花费很少的时间,不仅可以为这个项目带来很多好处,还可以在将来获得很多好处。
  2. 创建适合关系持久性的coordinates对象。
  3. 使用关系引用将转发的状态转回原始推文。
  4. 创建用户表并创建从string jsonResults = vontex.RawResults; Tweet的参考。
  5. 对于所有值类型对象,您有两个选项: 一个。如果它是单个值,例如Tweet,则将其展平为User。 湾如果它是一个多值,例如coordinates,则创建一个单独的表,其中实体拥有它自己的伪密钥并返回Tweet
  6. 我知道你想看代码。然而,这是一项巨大的工作,编写代码可以与我为您编写整个数据访问层相媲美,这对于论坛答案来说是不合理的。我仍然会继续使用NoSQL路线,除非有很难要求关系。希望这会有所帮助。

答案 1 :(得分:0)

如果您打算手动创建ID,可以从状态继承并添加类似的内容:

 [DatabaseGe‌​nerated(DatabaseGen‌​eratedOption.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; }

我希望它有所帮助。

答案 2 :(得分:0)

你看过了吗? 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());
}