1

我遇到了一个相当有趣的例外。它昨天发生在过去某个时候有效的代码上(我继承了大部分代码库,前开发人员不再和我们在一起)。

我昨天使用了一个解决方法.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
4

0 回答 0