0

我有一个任务来解析一些网站。解析一些帖子后,我有一个复杂的对象 Post 有很多评论,其中每个评论都有写它的用户和其他评论形式的一些答案。实际上类的结构会更复杂,但是,这里是例子(一些属性被遗漏了,没有必要):

public class Post : IParsedEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public string Title { get; set; }
    public string Text { get; set; }
    public User Author { get; set; }
    public IList<Comment> DownLevelComments { get; set; }
    public IList<Comment> AllComments { get; set; }

    public Post()
    {
        DownLevelComments = new List<Comment>();
        AllComments = new List<Comment>();
    }
}

public class User : IParsedEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string Name { get; set; }
    public string Url { get; set; }
}

public class Comment : IParsedEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public Post Post { get; set; }
    public User Author { get; set; }
    public Comment ParentComment { get; set; }

    public string Text { get; set; }

    public IList<Comment> SubComments { get; set; }

    public Comment()
    {
        SubComments = new List<Comment>();
    }
}

现在我配置我的数据库上下文:

        modelBuilder.Entity<Comment>().HasRequired(c => c.Post).WithMany(c => c.AllComments);
        modelBuilder.Entity<Post>().HasMany(c => c.DownLevelComments);            
        modelBuilder.Entity<Comment>().HasMany<Comment>(c => c.SubComments).WithOptional(c => c.ParentComment);

好的,我已经解析了一篇文章,现在我有一个 Post 实例,其中有很多其他类的实例链接到 post 的主要实例。

第一个问题:现在我有一个项目的多个实例('nsinreal' 有两条评论,所以我有重复的用户实例)。如果我尝试添加 Post 我会捕获异常,因为我有带有重复键的项目。好的,所以我需要编写自己的 TryAdd 方法来尝试添加实体和所有子项;我需要将具有相同主键的实例合并到一个实例;这一切都必须使用 EF 来完成,因为我的代码可以解析不同的帖子,并且同一用户可以出现在不同帖子的评论中。

第二个问题:我不能手动完成,因为它可能需要很多时间。我需要使用反射并使其自动工作。

第三个问题:解析和添加帖子必须在一台机器上使用不同的线程/任务。

目前我有递归函数 TryAdd ,它使步骤:

  1. 检查该实体尚未在上下文中
  2. 实体的 Foreach 属性(仅我们的原始 IParsedEntity 类)执行以下操作:
    1. 从实体中删除它以防止自动插入具有所有属性的所有实体。如果您有重复的用户,例如在帖子中至少出现两次的已解析用户,那就不好了。
    2. 尝试将属性值添加到数据库上下文并记住答案。必须使用反射魔法来提供泛型方法的正常工作
    3. 将数据库的答案或属性的原始值推送到特殊字典
  3. IList 的相同操作
  4. 将项目添加到上下文
  5. 恢复当前项目的所有属性和列表
  6. 仅将本地更改保存到数据库一次

不幸的是,这个算法在不同的线程上有问题。我必须如何重写它?

4

0 回答 0