我有一个实体,需要有多个另一个实体的列表。然而,这些列表中的每一个都将由相同类型的实体组成,这似乎使框架混淆。我读过这个问题:
Multiple collections of same type in entity framework
并遵循通过为每个项目列表继承不同类型来区分不同列表的建议。但这似乎没有做任何事情。
我得到的错误是:
Exception:Thrown: "Invalid column name 'ApprovalStage_Id1'.
Invalid column name 'ApprovalStage_Id2'.
Invalid column name 'ApprovalStage_Id3'." (System.Data.SqlClient.SqlException)
A System.Data.SqlClient.SqlException was thrown: "Invalid column name 'ApprovalStage_Id1'.
Invalid column name 'ApprovalStage_Id2'.
Invalid column name 'ApprovalStage_Id3'."
Time: 2/9/2015 3:22:05 PM
Thread:Worker Thread[11116]
这是我的实体。它有点密集,但基本上主要对象是ComplexApprovalProcess
,它在一个列表中有一些ApprovalStages
(这一切都很好)。问题在于,每个ApprovalStage
都有三个Approver
,“审批者”,“观看者”和“顾问”列表。当Entity尝试保存这些实体时,它会抛出上面的错误。就像我说的那样,我尝试通过继承Approver
中的其他三个类来区分它们,因此您可以看到它们现在是ReqApprover
,Advisor
和Viewer
的集合,但它仍然像以前一样抛出上面的错误。任何想法为什么实体会对此感到困惑?每个Approver
实体应该只返回它所属的ApprovalStage
,但实体似乎认为它应该引用三个不同的ApprovalStages
并尝试动态查找那些列,不存在。感谢。
实体:
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;
}
}
答案 0 :(得分:0)
好的,所以我想出了我正在犯的错误。我没有想到这样一个事实:一旦放入数据库,同一对象类型的不同列表就不知道它们来自哪个列表。也就是说,Approver,Advisor和Viewer在插入后对框架看起来都是一样的。随着Approvers的继承,我一直遇到错误,所以我简单地制作了3个不同的类和表,并将设计复制到每个类中,并且它完美地运行。简直不敢相信我花了这么多时间......