我遇到了一个相当有趣的例外。昨天发生的代码在过去的某个时刻起作用了(我继承了大部分代码库,前开发人员不再和我们在一起了)。
我昨天使用.Where()
应用了一个解决方法,但是因为我今天在另一个控制器中再次遇到了这个问题,所以我决定最好先找到它的底部然后把它咬到我意想不到的地方。
我收到以下错误:
发生了参照完整性约束违规:主键 作为参照完整性约束的一部分的属性不能 除非正在设置,否则在依赖对象未更改时更改 该协会的主要对象。主要对象必须是 跟踪并且没有标记为删除。
现在为了奇怪的部分。当我使用Find()方法DbContext.DbSet.Find(int)
和新的dbContext时,我收到此错误。
这是确切的代码。它在第5行找到了CurResponse对象而没有发生意外,但它失败并在遇到下面第7行的db.CurFundings.Find(post.SelectedSourceCurFundingKey);
时抛出上面的异常:
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);
我仍然得到上面的错误。
当我快速观察_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()
来获得我需要的东西,但我想确保这不是更深层次问题的迹象。
以下是整个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; }
}
}
以下是我可以从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