我在使用Entity Framework 4.1 Code First的ASP.NET MVC 3應用程序中遇到了一個有趣的錯誤。我有三個類/表按順序連接。有一個Invitation
參照Project
然後參考Company
。什麼會導致實體框架在現有數據上保存未加載(但延遲加載)的引用?
當我加載一家公司並保存它時,一切都很好。項目也是如此。但是,當邀請被編輯和保存時,它會抹去公司中的字段。他們都只是空白!
當我編輯項目時,我需要顯示公司的一些信息,所以我明確加載了.Include(x => x.Company)
。當我編輯邀請時,我不需要該公司,所以我沒有打擾包括它。
我想如果對象沒有加載過,那麼EF不應該有任何理由將其標記爲已編輯,對不對?
更新:通過註釋掉代碼行進行了很多調試後,我將其縮小了一些。
正在清除的實際對象是公司引用的Contact
對象。它並沒有真正被清除太多,因爲在構造函數中創建了一個新的聯繫人(所以對於新公司不會爲空)。
所以我想這改變了我的問題:有沒有辦法有一個引用屬性設置爲默認值而不會破壞EF?
public class InvitationController
{
[HttpPost]
public RedirectToRouteResult AcceptInvitation(int id, int companyId, int projectId, Invitation invitation)
{
// This line triggered the problem by loading a company, without
// eagerly loading the contacts.
CheckAuthorizationEdit(companyId, CommunicationService.GetById(id));
var dbResponse = InvitationService.GetPreviousResponse(companyId, projectId);
dbResponse.WillBid = invitation.WillBid;
InvitationService.Save(dbResponse);
return RedirectToAction("Response", new { id, companyId });
}
private void CheckAuthorizationEdit(int companyId, Communication communication)
{
var companyIds = communication.DistributionList.Companies.Select(c => c.Id).ToList();
//CheckAuthorization(companyIds);
}
}
public class InvitationService
{
public Invitation GetPreviousResponse(int companyId, int projectId)
{
return (from invitation in _db.Invitations
where invitation.ProjectId == projectId && invitation.SenderCompanyId == companyId
select invitation).SingleOrDefault();
}
public void Save(Invitation invitation)
{
_db.SaveChanges();
}
}
public class Invitation
{
public int Id { get; set; }
public int ProjectId { get; set; }
[ForeignKey("ProjectId")]
public virtual Project Project { get; set; }
// ...
}
public class Project
{
public int Id { get; set; }
public int CompanyId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
// ...
}
public class Company
{
public Company()
{
MainContact = new Contact();
}
public int Id { get; set; }
public virtual Contact MainContact { get; set; }
// ...
}
public class Contact
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
// ...
}
對!或者換句話說:如果對象沒有加載,那麼根本就沒有任何EF可以標記的東西。如果現有公司的字段在數據庫中被覆蓋,那麼在調用'SaveChanges'之前,在'Modified'狀態下的上下文中必須有一個具有相同鍵和空字段的實體。但是如果沒有看到代碼,很難說出發生了什麼。 – Slauma
我會嘗試提取足夠的代碼以發佈,而不會太過壓倒。相關部分分散一點。 –
獲取代碼發佈時,我注意到問題實際上是由引用屬性指向新的id而不是被覆蓋的舊引用的字段引起的。 –