尝试使用外键添加实体时违反主键

时间:2013-05-31 12:28:18

标签: c# entity-framework-5

我正在使用Entity Framework 5和代码优先方法。

我正在尝试做一个测试系统。它有五个类,一对一和一对多的关系。一个Test有一个TestInfo,一个用户有很多TestResults,一个TestResult有一个TestInfo和很多QuestionResults。它们是(没有一些简单的值类型属性):

public class TestInfo
{
    [Key]
    public virtual string Name { get; set; }
    public virtual TimeSpan Duration { get; set; }
}

public class Test
{
    [Key]
    public virtual int TestId { get; set; }
    public virtual TestInfo Info { get; set; }
    //some other stuff
    //...
}

public class User
{
    [Key]
    public virtual string Login { get; set; }

    List<TestResult> _results = new List<TestResult>();
    public virtual List<TestResult> Results
    {
        get { return _results; }
        set { _results = value; }
    }
    //...
}

public class TestResult
{
    [Key]
    public virtual int TestResultId { get; set; }
    public virtual TestInfo TestInfo { get; set; }
    //...

    private List<QuestionResult> _questionResults = new List<QuestionResult>();
    public virtual List<QuestionResult> QuestionResults
    {
        get { return _questionResults; }
        set { _questionResults = value; }
    }
}

public class QuestionResult
{
    [Key]
    public virtual int QuestionResultId { get; set; }
    //...
}

我的背景:

class TestContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Test> Tests { get; set; }
}

我正在尝试将现有用户的新TestResult添加到现有测试中(TestInfo是相同的):

public void AddTestResult(TestResult result)
{
    User user = _context.Users.Include(u => u.Results).FirstOrDefault(u => u.Login == _currentLogin);
    TestInfo existingTestInfo = _context.Tests.Where(t => t.Info.Name == result.TestInfo.Name).FirstOrDefault().Info;
    result.TestInfo = existingTestInfo;
    user.Results.Add(result);
    _context.SaveChanges();
}

当我这样做时,EF会抛出异常:

  

{“违反PRIMARY KEY约束'PK_dbo.TestInfoes'。无法在对象'dbo.TestInfoes'中插入重复键。重复键值为(第一次测试)。\ r \ n语句已终止。”} < / p>

如果我从TestResult类中删除QuestionResults属性,一切正常。这对我来说似乎很奇怪。 我做错了什么?

3 个答案:

答案 0 :(得分:0)

交换这两行:

user.Results.Add(result);
result.TestInfo = existingTestInfo;

user.Results.Add(result)将整个对象图标记为Added

答案 1 :(得分:0)

试试这个:

TestInfo existingTestInfo = _context.Tests.Where(t => t.Info.Name == result.TestInfo.Name).Include(i => i.TestInfos).FirstOrDefault().Info;

我也遇到了这个错误,直到我包含了子表,然后一切正常。

答案 2 :(得分:-1)

在单独的数据访问层(DAL)中使用EF5框架时遇到了这个问题。为了解决这个问题,我不得不遍历外键类并重新附加它们。我怀疑这是一个更好的方法,但这让我超越了这个职位。

if (db.Entry(result.TestInfo).State == EntityState.Detached)
    db.Entry(result.TestInfo).State = EntityState.Modified;

请告诉我这是否有帮助!