2011-03-06 59 views
0

我有我需要建模以下业务角色:继承和许多一对多的关系

  • 投标人可以,只要他们已经与这个人

  • 互动率卖家

    竞拍者只有在赢得拍卖时才能评价物品

  • 尽管卖家的最终评价是从物品评价和其他人的评价中取得的平均值。

  • 评分本身(无论是项目还是用户)是几个问题得分的平均值。

因此,我认为我应该创建一个Ratings类,然后用UserRating和ItemRating继承它。这两个应该有一个评级问题的ICollection(这将最终是一个静态表)。 UserRating的问题与ItemRating的问题不同,但我认为为这些问题创建单独的表/实体并不值得(或者我应该做一个TPH继承?)。

所以,在这里就是我有这么远:

public abstract class Rating 
{ 
    public int Id { get; set; } 

    public virtual User By { get; set; } 
} 

public class UserRating : Rating 
{ 
    public virtual User For { get; set; } 

    public virtual ICollection<RatingQuestion> Questions { get; set; } 
} 


public class ItemRating : Rating 
{ 
    public virtual Item For { get; set; } 

    public virtual ICollection<RatingQuestion> Questions { get; set; } 
} 


public class RatingQuestion 
{ 
    public int Id { get; set; } 

    public string Text { get; set; } 

    public virtual ICollection<Rating> Rating { get; set; } 
} 

为什么我把ICollection的子类中,而不是评级基类的原因是因为两者的RatingQuestion是不同的,但我我不确定这是我应该怎么做的,如果我错了,请纠正我。

我需要一些帮助的一件事是决定是否去TPH或TPT继承。我想保持简单,但我也想保持我的数据库正常化。而且,绩效是一个需要考虑的因素。

现在,我需要知道如何做的最后一件事是:如何映射评级类(基类或子类,不知道应该使用哪一个)之间的多对多关系,和使用Fluent API的RatingQuestion类,并添加属性(分数),这是属性关系本身,因此我可以在每个单独的RatingQuestion上记录分数。

我希望这已经够清楚了。所有建议都非常受欢迎。提前致谢!

UPDATE:(拉吉斯拉夫Mrnka的答案后)

public abstract class Rating 
{ 
    public int Id { get; set; } 
    public virtual User By { get; set; } 
    public virtual ICollection<RatingQuestion> RatingQuestions { get; set; } 
} 

public class UserRating : Rating 
{ 
    public virtual User For { get; set; } 
    public virtual ICollection<Question> Questions { get; set; } 
} 

public class ItemRating : Rating 
{ 
    public virtual Item For { get; set; } 
    public virtual ICollection<Question> Questions { get; set; } 
} 

public class User 
{ 
    public int Id { get; set; } 
    //more properties 
    public virtual ICollection<UserRating> OwnRatings { get; set; } 
    public virtual ICollection<UserRating> RatingsForOthers { get; set; } 
    public virtual ICollection<ItemRating> ItemRatings { get; set; } 
} 

public class Item 
{ 
    public int Id { get; set; } 
    //more properties 
    public virtual ItemRating Rating { get; set; } //because an Item will have only one rating 
} 

public class UserRatingConfiguration : EntityTypeConfiguration<UserRating> 
{ 
    public UserRatingConfiguration() 
    { 
     HasOptional(p => p.By) 
      .WithMany(u => u.RatingsForOthers) 
      .IsIndependent() 
      .Map(m => m.MapKey(c => c.Id, "RatingSubmitter")); 

     HasRequired(p => p.For) 
      .WithMany(u => u.OwnRatings) 
      .IsIndependent() 
      .Map(m=>m.MapKey(c => c.Id, "RatedSeller")); 
    } 
} 

public class ItemRatingConfiguration : EntityTypeConfiguration<ItemRating> 
{ 
    public ItemRatingConfiguration() 
    { 
     HasRequired(p => p.By) 
      .WithMany(u => u.ItemRatings) 
      .IsIndependent() 
      .Map(m=>m.MapKey(c => c.Id, "ItemRatingSubmitter")); 
    } 
} 

我得到在SQL Server中,这显然是被我搞砸映射造成了非常搞砸模型。任何建议,或者我应该只是遗忘了继承和DRY原则在一起的情况?

回答

1

如果您需要将自定义属性添加到该关系,则不能使用直接M:N映射。在这种情况下,您需要将交接表建模为另一个实体,该实体将参照RatingQuestion并且还包括Score属性。

我会推荐使用TPH继承。它使用起来更容易,性能更好。 TPT的构造确实是ugly queries。也没有理由在派生类中有RatingQuestions。这两个集合都引用相同的类型,因此您可以将其移至父级。此外,根据this question,在使用TPH时,子类中的导航属性存在一些问题。我不确定这个问题在Code-first中是否仍然有效。无论如何,你现在的模型根本不需要孩子的导航属性。

如果你按照我的建议,你不需要添加任何映射。在使用这些类时,它将使用默认约定进行映射:

public abstract class Rating 
{ 
    public virtual int Id { get; set; } 
    public virtual User By { get; set; } 

    private ICollection<RatingQuestion> _ratingQuestions = null; 
    public ICollection<RatingQuestion> RatingQuestions 
    { 
     get 
     { 
      if (_ratingQuestions == null) 
      { 
       _ratingQuestions = new HashSet<RatingQuestion>(); 
      } 
      return _ratingQuestions; 
     } 
     protected set { _ratingQuestions = value; } 
    } 
} 

public class ItemRating : Rating 
{ 
    public virtual Item For { get; set; } 
} 

public class UserRating : Rating 
{ 
    public virtual User For { get; set; } 
} 

public class RatingQuestion 
{ 
    public virtual int Id { get; set; } 
    public virtual int Score { get; set; } 
    public virtual Rating Rating { get; set; } 
    public virtual Question Question { get; set; } 
} 

public class Question 
{ 
    public virtual int Id { get; set; } 
    public virtual string Text { get; set; } 

    private ICollection<RatingQuestion> _ratingQuestions = null; 
    public ICollection<RatingQuestion> RatingQuestions 
    { 
     get 
     { 
      if (_ratingQuestions == null) 
      { 
       _ratingQuestions = new HashSet<RatingQuestion>(); 
      } 
      return _ratingQuestions; 
     } 
     protected set { _ratingQuestions = value; } 
    } 
} 
+0

这虽然有些帮助,但我仍然遇到了映射问题。我需要使用Fluent API来将事情组织在生成的数据库中。我会更新我的初始文章,以便您了解我们现在处理的内容。 – Kassem 2011-03-06 16:39:07

+0

@Kassem:如果您在评分中有By字段,则不能有两个单独的集合 - 一个用于UserRating和一个用于ItemRating。评级只能有一个。另外我不明白为什么衍生评级仍然有问题的集合。 – 2011-03-06 20:43:54

+0

哦,我的坏,我忘了从派生类中删除ICollection,现在修复。你能编辑你的文章并告诉我怎样才能解决By字段问题吗?非常感谢! – Kassem 2011-03-06 21:18:03