使用重复值添加复杂对象(解析站点后)

时间:2013-07-01 20:04:43

标签: c# multithreading entity-framework

我有一个解析某个网站的任务。在解析了一些帖子后,我有一个复杂的对象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 i捕获异常,因为我有重复键的项目。好的,所以我需要编写自己的TryAdd方法来尝试添加实体和所有子项;我需要将具有相同主键的实例合并到一个实例;这一切都必须使用EF完成,因为我的代码可以解析不同的帖子,同一个用户可以出现在不同帖子的评论中。

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

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

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

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

0 个答案:

没有答案