Entity framework 4 继承和多对多关系

Entity framework 4 继承和多对多关系,entity-framework-4,ef-code-first,Entity Framework 4,Ef Code First,我需要扮演以下业务角色: 投标人可以给卖家打分,只要他们与此人互动过 只有在拍卖中获胜的情况下,出价人才能对物品进行估价 不过,卖家的最终评级是从物品评级和其他人对自己的评级中得出的平均值 评分本身(无论是针对项目还是用户)是几个问题的平均分数 因此,我认为应该创建一个Ratings类,然后用UserRating和ItemRating继承它。这两个表都应该有一个RatingQuestion的ICollection(最终将是一个静态表)。UserRating的问题与ItemRating的问题不

我需要扮演以下业务角色:

  • 投标人可以给卖家打分,只要他们与此人互动过

  • 只有在拍卖中获胜的情况下,出价人才能对物品进行估价

  • 不过,卖家的最终评级是从物品评级和其他人对自己的评级中得出的平均值

  • 评分本身(无论是针对项目还是用户)是几个问题的平均分数

因此,我认为应该创建一个Ratings类,然后用UserRating和ItemRating继承它。这两个表都应该有一个RatingQuestion的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; }
}
公共抽象类评级
{
公共int Id{get;set;}
通过{get;set;}公开虚拟用户
}
公共类用户评级:评级
{
{get;set;}的公共虚拟用户
公共虚拟ICollection问题{get;set;}
}
公共类项目评级:评级
{
{get;set;}的公共虚拟项
公共虚拟ICollection问题{get;set;}
}
公开课评分问题
{
公共int Id{get;set;}
公共字符串文本{get;set;}
公共虚拟ICollection分级{get;set;}
}
我之所以将ICollection放在子类而不是评级基类中,是因为两者的评级问题不同,但我不确定我应该这样做,如果我错了请纠正我

有一件事我需要一些帮助,那就是决定是选择TPH还是TPT继承。我想让事情保持简单,但我也希望让我的数据库规范化。此外,绩效是一个需要考虑的因素

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

我希望这已经足够清楚了。欢迎提出所有建议。提前谢谢

更新:(在Ladislav Mrnka的回答之后)

公共抽象类评级
{
公共int Id{get;set;}
通过{get;set;}公开虚拟用户
公共虚拟ICollection分级问题{get;set;}
}
公共类用户评级:评级
{
{get;set;}的公共虚拟用户
公共虚拟ICollection问题{get;set;}
}
公共类项目评级:评级
{
{get;set;}的公共虚拟项
公共虚拟ICollection问题{get;set;}
}
公共类用户
{
公共int Id{get;set;}
//更多属性
公共虚拟ICollection OwnRatings{get;set;}
公共虚拟ICollection RatingsRothers{get;set;}
公共虚拟ICollection ItemRatings{get;set;}
}
公共类项目
{
公共int Id{get;set;}
//更多属性
公共虚拟项目评级{get;set;}//因为一个项目将只有一个评级
}
公共类UserRatingConfiguration:EntityTypeConfiguration
{
公共UserRatingConfiguration()
{
hasby可选(p=>p.By)
.有许多(u=>u.RatingsFrother)
.IsIndependent()
.Map(m=>m.MapKey(c=>c.Id,“评级提交人”);
HASSrequired(p=>p.For)
.有许多(u=>u.OwnRatings)
.IsIndependent()
.Map(m=>m.MapKey(c=>c.Id,“RatedSeller”);
}
}
公共类ItemRatingConfiguration:EntityTypeConfiguration
{
public ItemRatingConfiguration()
{
HasRequired(p=>p.By)
.有许多(u=>u.ItemRatings)
.IsIndependent()
.Map(m=>m.MapKey(c=>c.Id,“ItemRatingSubmitter”);
}
}

我在SQL Server中得到了一个非常混乱的模型,这显然是由我混乱的映射造成的。有什么建议吗?或者我应该把继承和DRY原则都忘了吗?

如果需要向该关系添加自定义属性,则不能使用直接M:N映射。在这种情况下,您需要将连接表建模为另一个实体,该实体将引用
评级
问题
,还包括
评分
属性

我建议使用TPH继承。它更易于使用,并且具有更好的性能。TPT结构真的很复杂。此外,在派生类中也没有理由有评级问题。这两个集合引用相同的类型,因此您可以将其移动到父级。此外,据了解,在使用TPH时,子类中的导航属性存在一些问题。我不确定这个问题在代码中是否仍然有效。无论如何,您当前的模型不需要在子对象上使用导航属性

如果您遵循我的建议,则不需要添加任何映射。当使用这些类时,它将映射为默认约定:

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; }
    }
}
公共抽象类评级
{
公共虚拟整数Id{get;set;}
通过{get;set;}公开虚拟用户
private ICollection _ratingQuestions=null;
公共信息收集评分问题
{
得到
{
如果(_ratingQuestions==null)
{
_ratingQuestions=新哈希集();
}
返回评级问题;
}
受保护集{u ratingQuestions=value;}
}
}
公共类项目评级:评级
{
{get;set;}的公共虚拟项
}
公共类用户评级:评级
{
{get;set;}的公共虚拟用户
}
公开课评分问题
{
公共虚拟整数Id{get;set;}
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; }
    }
}