我遇到了一个相当有趣的例外。它昨天发生在过去某个时候有效的代码上(我继承了大部分代码库,前开发人员不再和我们在一起)。
我昨天使用了一个解决方法.Where()
,但是由于我今天在另一个控制器中再次遇到了这个问题,我决定最好在它把我咬到意想不到的地方之前找到它的底部。
我收到以下错误:
发生参照完整性约束冲突:当从属对象未更改时,作为参照完整性约束一部分的主键属性不能更改,除非它被设置为关联的主体对象。必须跟踪主体对象并且不标记为删除。
现在是奇怪的部分。当我将 Find() 方法DbContext.DbSet.Find(int)
与新的 dbContext 一起使用时出现此错误。
这是确切的代码。它在第 5 行找到了 CurResponse 对象而没有发生意外,但它在遇到db.CurFundings.Find(post.SelectedSourceCurFundingKey);
下面的第 7 行时失败并抛出上面的异常:
0. [HttpPost]
1. public ActionResult MatchingCur2Fundings(int id, MatchingCur2FundingsVM post, string callbackId)
2. {
3. if (ModelState.IsValid)
4. {
5. var cur = _db.CurResponses.Find(id);
6. var c2f = new Cur2FundingDataFlow();
7. c2f.SourceFunding = _db.CurFundings.Find(post.SelectedSourceCurFundingKey);
我post.SelectedSourceCurFundingKey
用如下整数替换:
7. c2f.SourceCurFunding = _db.CurFundings.Find(1);
我仍然得到上面的错误。
当我 quickwatch 时_db.CurFundings
,它返回 3 个对象,其中一个对象的主键为1。
当我快速观看时, db.CurFundings.Find(post.SelectedSourceCurFundingKey);
我得到了上面的错误,所以它与作业左侧的内容没有任何关系。
我可以通过将 替换为 来获得我需要的项目DbContext.DbSet.Find()
,DbContext.DbSet.Where(x => x.id == id).SingleOrDefault()
如下所示:
c2f.SourceCurFunding = _db.CurFundings.Where(cf => cf.CurFundingKey == post.SelectedSourceCurFundingKey).SingleOrDefault();
仅当我使用该Find()
方法从 DbContext 检索项目时才会出现此问题。
我正在使用 EF CodeFirst,当前的大部分代码都是几个月前继承的。
我不知道这是否会有所帮助,但这是将此特定对象添加到我的 DbContext 的行:
public DbSet<CuFunding> CurFundings { get; set; }
这是应用程序中对该属性的唯一引用DbContext.CurFundings
,当我查看该类型的用法时,我没有看到任何奇怪的事情发生。
我总是可以使用.Where()
来获得我需要的东西,但我想确保这不是更深层次问题的迹象。
编辑 1
这是整个 CurFunding 类CurConstructionFunding
,但我在前面的示例中缩短了名称:
namespace MfpSuite.Models.Documents.CUR
{
public class CurConstructionFunding
{
[Key]
public int CurConstructionFundingKey { get; set; }
public int CurPropertyKey { get; set; }
[ForeignKey("CurPropertyKey")]
public virtual CurProperty CurProperty { get; set; }
public string Source { get; set; }
public string Lender { get; set; }
public string ConstructionAmount { get; set; }
public string PermanentAmount { get; set; }
public string PermanentLoanPerUnit { get; set; }
public string TotalConstructionAmount { get; set; }
public string TotalPermanentAmount { get; set; }
public string TotalPermanentLoanPerUnit { get; set; }
//public int CurResponseKeyId { get; set; }
//[ForeignKey("CurResponseKeyId")]
//public virtual CurResponse CurResponse { get; set; }
/// <summary>
/// Indicates which funding this data is imported into. Note there shouldn't be more than one item in this collection.
/// 01/14/13 - todo - if there shouldn't be more than one, this should be a 1|1 mapping here (like we have [mistakenly] done w/ docTypes to Doc)
/// </summary>
public virtual ICollection<Cur2FundingDataFlow> Cur2FundingDataFlow { get; set; }
}
}
编辑 2
这是我可以从快速观察中得到的Find()
:
_db.CurConstructionFundings = {SELECT
[Extent1].[CurConstructionFundingKey] AS [CurConstructionFundingKey],
[Extent1].[CurPropertyKey] AS [CurPropertyKey],
[Extent1].[Source] AS [Source],
[Extent1].[Lender] AS [Lender],
[Extent1].[ConstructionAmount] AS [ConstructionAmount],
...
_db.CurConstructionFundings
{SELECT
[Extent1].[CurConstructionFundingKey] AS [CurConstructionFundingKey],
[Extent1].[CurPropertyKey] AS [CurPropertyKey],
[Extent1].[Source] AS [Source],
[Extent1].[Lender] AS [Lender],
[Extent1].[ConstructionAmount] AS [ConstructionAmount],
[Extent1].[PermanentAmount] AS [PermanentAmount],
[Extent1].[PermanentLoanPerUnit] AS [PermanentLoanPerUnit],
[Extent1].[TotalConstructionAmount] AS [TotalConstructionAmount],
[Extent1].[TotalPermanentAmount] AS [TotalPermanentAmount],
[Extent1].[TotalPermanentLoanPerUnit] AS [TotalPermanentLoanPerUnit]
FROM [dbo].[CurConstructionFundings] AS [Extent1]}
StackTrace " at System.Data.Objects.ObjectStateManager.DetectConflicts(IList`1 entries)\r\n
at System.Data.Objects.ObjectStateManager.DetectChanges()\r\n
at System.Data.Objects.ObjectContext.DetectChanges()\r\n
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)\r\n
at System.Data.Entity.Internal.Linq.InternalSet`1.Find(Object[] keyValues)\r\n
at System.Data.Entity.DbSet`1.Find(Object[] keyValues)" string
+ [System.Reflection.RuntimeMethodInfo] {Void DetectConflicts(System.Collections.Generic.IList`1[System.Data.Objects.EntityEntry])} System.Reflection.RuntimeMethodInfo