C# 如何在同一类型的实体中有多个列表?

C# 如何在同一类型的实体中有多个列表?,c#,asp.net-mvc,entity-framework,table-per-type,C#,Asp.net Mvc,Entity Framework,Table Per Type,我有一个实体需要有另一个实体的多个列表。然而,这些列表中的每一个都将由相同类型的实体组成,这似乎混淆了框架。我读过这个问题: 并遵循通过为每个项目列表继承不同类型来区分不同列表的建议。但这似乎没什么作用 我得到的错误是: 异常:引发:列名“ApprovalStage_Id1”无效。 列名“ApprovalStage_Id2”无效。 列名“ApprovalStage_Id3”无效。System.Data.SqlClient.SqlException 引发System.Data.SqlClient.

我有一个实体需要有另一个实体的多个列表。然而,这些列表中的每一个都将由相同类型的实体组成,这似乎混淆了框架。我读过这个问题:

并遵循通过为每个项目列表继承不同类型来区分不同列表的建议。但这似乎没什么作用

我得到的错误是:

异常:引发:列名“ApprovalStage_Id1”无效。 列名“ApprovalStage_Id2”无效。 列名“ApprovalStage_Id3”无效。System.Data.SqlClient.SqlException 引发System.Data.SqlClient.SqlException:列名“ApprovalStage_Id1”无效。 列名“ApprovalStage_Id2”无效。 列名“ApprovalStage_Id3”无效。 时间:2015年2月9日下午3:22:05 线程:工作线程[11116]

这里是我的实体。它有点密集,但基本上主要对象是ComplexApprovalProcess,它在一个列表中有一些ApprovalStage,这很好。问题在于,每个ApprovalStage都有三个审批者列表,“审批者”、“查看者”和“顾问”。当实体试图保存这些实体时,会抛出上面的错误。正如我所说,我试图通过从Approver继承其他三个类来区分这些类,因此您可以看到它们现在是ReqApprover、Advisor和Viewer的集合,但它仍然像以前一样抛出上面的错误。你知道为什么实体会对此感到困惑吗?每个审批人实体应该只引用回它所属的ApprovalStage,但该实体似乎认为它应该引用三个不同的ApprovalStage,并尝试动态查找那些不存在的列。谢谢

实体:

public class ComplexApprovalProcess
{
    [Key]
    public long Id { get; set; }

    [InverseProperty("ApprovalProcessId")]
    public List<ApprovalStage> Stages { get; set; }

    [ForeignKey("Form")]
    public long FormId { get; set; }

    public int CurrentStage { get; set; }

    public FormBase Form { get; set; }

    bool Approved { get; set; }

    bool Denied { get; set; }

    private bool CheckCompleted() {

        foreach (ApprovalStage stage in this.Stages)
        {
            if (stage.Completed == false)
            {
                //if any stage is incomplete, the process is not complete
                return false;
            }
        }
        //no stages incomplete means all stages complete
        return true;
    }

    private bool AdvanceStage()
    { 
        //check the completion condition of the current stage, if completed, advance to next stage
        ApprovalStage current = Stages.Where(m => m.StageOrder == this.CurrentStage).FirstOrDefault();

        if (current != null)
        {
            //check if stage is completed
            if (current.CheckCompletion())
            {
                //check if stage is approved
                if (current.Approved)
                {
                    //check if process contains additional stages
                    if (this.Stages.Count > this.CurrentStage)
                    { 
                        //Move to next stage
                        this.CurrentStage += 1;
                        ApprovalStage next = Stages.Where(m => m.StageOrder == this.CurrentStage).FirstOrDefault();

                        if (next != null)
                        {
                            next.StartStage();
                        }
                        else
                        {
                            throw new Exception("Huh?");
                        }
                    }
                }
            }
        }
        else
        {
            throw new Exception("Wut");
        }
        return false;
    }

    public static ComplexApprovalProcess CreateCheckRequestApprovalProcess(FormBase form)
    {
        UsersModel user = null;

        ComplexApprovalProcess process = new ComplexApprovalProcess();

        using (TechnologyProjectPlanContext db = new TechnologyProjectPlanContext())
        {
            int id = SessionVar.Get<int>(SessionVar.USERID);

            user = db.UsersModels.Where(m => m.Id == id).FirstOrDefault();
        }

        process.Form = form;

        ApprovalStage InitialReview = new ApprovalStage();
        InitialReview.StageOrder = 1;
        InitialReview.Approvers = new List<ReqApprover>();
        InitialReview.Advisors = new List<Advisor>();
        InitialReview.Viewers = new List<Viewer>();
        InitialReview.Form = form;

        InitialReview.ApprovalProcess = process;
        InitialReview.Approvers.Add(new ReqApprover(user, form, InitialReview));
        InitialReview.Advisors.Add(new Advisor(user, form, InitialReview));
        InitialReview.Viewers.Add(new Viewer(user, form, InitialReview));
        InitialReview.StageName = "Initial Review";

        ApprovalStage MiddleApproval = new ApprovalStage();
        MiddleApproval.StageOrder = 2;
        MiddleApproval.Approvers = new List<ReqApprover>();
        MiddleApproval.Advisors = new List<Advisor>();
        MiddleApproval.Viewers = new List<Viewer>();
        MiddleApproval.Form = form;

        MiddleApproval.ApprovalProcess = process;
        MiddleApproval.Approvers.Add(new ReqApprover(user, form, MiddleApproval));
        MiddleApproval.Advisors.Add(new Advisor(user, form, MiddleApproval));
        MiddleApproval.Viewers.Add(new Viewer(user, form, MiddleApproval));
        MiddleApproval.StageName = "Middle Approval";


        ApprovalStage FinalApproval = new ApprovalStage();
        FinalApproval.StageOrder = 3;
        FinalApproval.Approvers = new List<ReqApprover>();
        FinalApproval.Advisors = new List<Advisor>();
        FinalApproval.Viewers = new List<Viewer>();
        FinalApproval.Form = form;

        FinalApproval.ApprovalProcess = process;
        FinalApproval.Approvers.Add(new ReqApprover(user, form, FinalApproval));
        FinalApproval.Advisors.Add(new Advisor(user, form, FinalApproval));
        FinalApproval.Viewers.Add(new Viewer(user, form, FinalApproval));
        FinalApproval.StageName = "Final Approval";

        process.Stages = new List<ApprovalStage>();
        process.Stages.AddRange(new ApprovalStage[] { InitialReview, MiddleApproval, FinalApproval });

        //set default values
        process.Approved = false;
        process.Denied = false;

        process.CurrentStage = 1;
        process.Stages[0].StartStage();
        return process;
    }

    public void SaveToDb()
    {
        //make sure we have at least one stage and either a form reference (new form) or form id (old form) before moving forward
        if ((Stages != null && Stages.Count > 0) && (Form != null || FormId > 0))
        { 
            using (TechnologyProjectPlanContext  db = new TechnologyProjectPlanContext())
            {
                //first we have to save the process to get an Id
                //copy stages out so we can save without the fuss
                List<ApprovalStage> stages = this.Stages;

                this.Stages = null;

                db.ComplexApprovalProcesses.Add(this);
                db.SaveChanges();

                //'this' now has an Id

                //ok let's work it out from the bottom to the top, first separate out approvers from stages and save:
                foreach (ApprovalStage stage in stages)
                {
                    ICollection<ReqApprover> approvers = stage.Approvers;
                    ICollection<Advisor> advisors = stage.Advisors;
                    ICollection<Viewer> viewers = stage.Viewers;

                    stage.FormId = stage.Form.Id;
                    stage.Form = null;

                    stage.Approvers = null;
                    stage.Advisors = null;
                    stage.Viewers = null;

                    stage.ApprovalProcessId = this.Id;

                    db.ApprovalStages.Add(stage);
                    db.SaveChanges();

                    //stage now has an id;
                    //iterate through each set of approvers and save
                    foreach (Approver approver in approvers)
                    {
                        approver.FormId = stage.FormId;
                        approver.UserId = approver.User.Id;
                        approver.ApprovalStage_Id = stage.Id;

                        approver.Form = null;
                        approver.User = null;
                        approver.Stage = null;

                        db.Approvers.Add(approver);
                        db.SaveChanges();
                    }

                    foreach (Advisor approver in advisors)
                    {
                        approver.FormId = stage.FormId;
                        approver.UserId = approver.User.Id;
                        approver.ApprovalStage_Id = stage.Id;

                        approver.Form = null;
                        approver.User = null;
                        approver.Stage = null;

                        db.Approvers.Add(approver);
                    }

                    foreach (Viewer approver in viewers)
                    {
                        approver.FormId = stage.FormId;
                        approver.UserId = approver.User.Id;
                        approver.ApprovalStage_Id = stage.Id;

                        approver.Form = null;
                        approver.User = null;
                        approver.Stage = null;

                        db.Approvers.Add(approver);
                    }
                    db.SaveChanges();
                }
            }
        }
    }
}

public class ApprovalStage
{
    //Each stage requires at least one approver
    [Key]
    public long Id { get; set; }

    [ForeignKey("ApprovalProcess")]
    public long ApprovalProcessId { get; set; }

    [ForeignKey("Form")]
    public long FormId { get; set; }

    public FormBase Form { get; set; }

    public ComplexApprovalProcess ApprovalProcess { get; set; }

    public ICollection<ReqApprover> Approvers { get; set; } //These users are required to approve before the form can move to the next stage.

    public ICollection<Advisor> Advisors { get; set; } //These users can see the form and approve at this stage, but they are not required.

    public ICollection<Viewer> Viewers { get; set; } //These users can see the form, but cannot approve

    public string StageName { get; set; } //Name of stage e.g. Review, Final Approval, etc.  Gives a custom feel?

    public int StageOrder { get; set; }

    public bool Completed { get; set; }

    public bool Approved { get; set; }

    public bool Denied { get; set; }

    public bool CanAbstain { get; set; }

    public ApprovalStage()
    { 
        this.Approved = false;
        this.Denied = false;
        this.Completed = false;
    }
}

public class Approver
{
    [Key]
    public long Id { get; set; }

    [ForeignKey("User")]
    public int UserId { get; set; }

    public UsersModel User { get; set; }

    [ForeignKey("Form")]
    public long FormId { get; set; }

    public FormBase Form { get; set; }

    [ForeignKey("Stage")]
    public long ApprovalStage_Id { get; set; }

    public ApprovalStage Stage { get; set; }

    public bool Approved { get; set; }

    public bool Denied { get; set; }

    public bool Abstain { get; set; }

    public Approver() { }

    public Approver(UsersModel user, FormBase form, ApprovalStage stage)
    {
        this.Stage = stage;
        this.User = user;
        this.Approved = false;
        this.Denied = false;
        this.Abstain = false;
    }
}

好吧,我算出了我犯的错误。我没有想到,一旦放入数据库,相同对象类型的不同列表将不知道它们来自哪个列表。也就是说,批准者、顾问和查看者在插入后在框架中看起来都是一样的。我在继承Approvers的过程中不断遇到错误,因此我只制作了3个不同的类和表,并将设计复制到每个类和表中,结果非常完美。真不敢相信我在这上面花了这么多时间