Entity Framework 添加没有 ID 的数据时抛出错误

Entity Framework throwing an error when adding data without IDs

我有一个 returns 推文列表的功能。该列表中的每个元素都有很多数据,推文的文本、位置、用户信息,如果它是转推,它的时间、转推信息、图片链接,以及更多数据,数据列表列表。

我正在使用 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); :

One or more validation errors were detected during model generation:

DataAcquirer.Models.Status: : EntityType 'Status' has no key defined. Define the key for this EntityType. DataAcquirer.Models.Coordinate: : EntityType 'Coordinate' has no key defined. Define the key for this EntityType. DataAcquirer.Models.Entities: : EntityType 'Entities' has no key defined. >Define the key for this EntityType. DataAcquirer.Models.HashTagEntity: : EntityType 'HashTagEntity' has no key defined. Define the key for this EntityType. DataAcquirer.Models.PhotoSize: : EntityType 'PhotoSize' has no key defined. Define the key for this EntityType. DataAcquirer.Models.VideoInfo: : EntityType 'VideoInfo' has no key defined. Define the key for this EntityType. DataAcquirer.Models.Variant: : EntityType 'Variant' has no key defined. Define the key for this EntityType. DataAcquirer.Models.SymbolEntity: : EntityType 'SymbolEntity' has no key defined. Define the key for this EntityType. DataAcquirer.Models.UrlEntity: : EntityType 'UrlEntity' has no key defined. Define the key for this EntityType. DataAcquirer.Models.UserMentionEntity: : EntityType 'UserMentionEntity' has no key defined. Define the key for this EntityType. DataAcquirer.Models.Geometry: : EntityType 'Geometry' has no key defined. Define the key for this EntityType. DataAcquirer.Models.User: : EntityType 'User' has no key defined. Define the key for this EntityType. DataAcquirer.Models.BannerSize: : EntityType 'BannerSize' has no key defined. Define the key for this EntityType. DataAcquirer.Models.Category: : EntityType 'Category' has no key defined. Define the key for this EntityType. Tweets: EntityType: EntitySet 'Tweets' is based on type 'Status' that has no keys defined. Coordinates: EntityType: EntitySet 'Coordinates' is based on type 'Coordinate' that has no keys defined. Entities: EntityType: EntitySet 'Entities' is based on type 'Entities' that has no keys defined. HashTagEntities: EntityType: EntitySet 'HashTagEntities' is based on type 'HashTagEntity' that has no keys defined. PhotoSizes: EntityType: EntitySet 'PhotoSizes' is based on type 'PhotoSize' that has no keys defined. VideoInfoes: EntityType: EntitySet 'VideoInfoes' is based on type 'VideoInfo' that has no keys defined. Variants: EntityType: EntitySet 'Variants' is based on type 'Variant' that has no keys defined. SymbolEntities: EntityType: EntitySet 'SymbolEntities' is based on type 'SymbolEntity' that has no keys defined. UrlEntities: EntityType: EntitySet 'UrlEntities' is based on type 'UrlEntity' that has no keys defined. UserMentionEntities: EntityType: EntitySet 'UserMentionEntities' is based on type 'UserMentionEntity' that has no keys defined. Geometries: EntityType: EntitySet 'Geometries' is based on type 'Geometry' that has no keys defined. Users: EntityType: EntitySet 'Users' is based on type 'User' that has no keys defined. BannerSizes: EntityType: EntitySet 'BannerSizes' is based on type 'BannerSize' that has no keys defined. Categories: EntityType: EntitySet 'Categories' is based on type 'Category' that has no keys defined.

class 看起来像下面这样:

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 继承并添加类似这样的内容:

 [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; }

希望对您有所帮助。

你看过了吗 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 returns 对象是分层的而非关系的。例如下面是 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中的RetweetedStatus到 Twitter),它是 TweetTweet 类型 属性,userUser 类型的 属性 12=]。在 RetweetedStatusUser 中是更复杂的对象。

针对您遇到的问题,请注意 coordinates 属性。它没有 ID 因为它主要是一个值。也许将其建模为语义结构会更好,也许这是我在这里的收获之一,但事实是它没有,也永远不会有 ID。如果您查看错误消息中的项目列表,您会发现大多数错误都是针对值类型对象的,例如 coordinates.

一种方法是不坚持关系模型,而是寻找能够满足您需求的 NoSQL 选项。例如MongoDB 或 Microsoft 的新 CosmosDB - 还有无数的选择。我在自己的代码中采用了这种方法,因为虽然现在 Twitter API 更加自律,但它过去常常变化莫测。也就是说,关系方法现在可能是可行的。在这种方法中,您可以像这样从 Twitter 读取原始内容:

string jsonResults = vontex.RawResults;

然后您可以使用 Json.NET 提取个人推文。

以下是我将使用关系方法执行的操作:

  1. 使用Automapper。学习此工具所需的少量时间不仅会在这个项目中而且在未来都会带来很多好处。
  2. 为关系持久性创建您自己的 Tweet 对象 suitable。
  3. 使用关系引用将转发的状态引用回原始推文。
  4. 创建用户 table 并创建从 TweetUser 的引用。
  5. 对于所有值类型对象,您有两种选择: 一种。如果它是单个值,例如 coordinates,请将其展平为 Tweet。 b.如果它是一个多值,例如 entities,请创建一个单独的 table,其中实体拥有自己的伪键并返回到 Tweet.

我知道你想看代码。但是,这是一项艰巨的工作,编写代码相当于我为您编写整个数据访问层,这对于论坛回答来说是不合理的。我仍然会走 NoSQL 路线,除非有一个硬性要求去关系。希望这会有所帮助。