C# 如何在同一类型的实体中有多个列表?
我有一个实体需要有另一个实体的多个列表。然而,这些列表中的每一个都将由相同类型的实体组成,这似乎混淆了框架。我读过这个问题: 并遵循通过为每个项目列表继承不同类型来区分不同列表的建议。但这似乎没什么作用 我得到的错误是: 异常:引发:列名“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,并尝试动态查找那些不存在的列。谢谢 实体: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.
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个不同的类和表,并将设计复制到每个类和表中,结果非常完美。真不敢相信我在这上面花了这么多时间