EF SaveChanges()抛出异常'只有在属性的当前值为null时才能设置EntityKey属性'

时间:2011-07-05 09:28:20

标签: entity-framework

我一直在阅读我发现的有关EF的所有类似帖子,但我仍然无法找到解决方案。

我是EF的新手,我一直在阅读一些有关使用它的有用信息,但我认为我错过了一些东西。

场景是这样的:

我希望用户能够在ASP.NET网页中创建帐户。所以我有一个名为'Accounts'的表。用户必须同意网站的条件条款,可以在futere中更新,因此我还有一个名为“ConditionTerms”的表,该表与帐户有1对多的关系(许多帐户都有唯一的条件术语)。 / p>

我想从帐户数据中分离出特定的个人用户数据,因此我还创建了一个名为“人员”的表格,并设置了关系,以便一个人拥有多个帐户。

现在,当我想将帐户保存到数据库中时,我检索数据库中可用的最后一个conditionTerm并将其附加到帐户实体。然后,当我尝试通过SaveChanges()保存数据时,我得到了帖子标题中提到的异常。问题是如果所有实体都是新的,当创建关联时,所有项的EntityState都是'Detached'并且它可以工作,但是当我从数据库中检索现有的conditionTerm并将其添加到account.ConditionTerm时,帐户将其状态更改为“已添加”,然后它会抛出异常。

我在某处读到,当发生这种情况时,它意味着所有实体树都被认为已经被上下文添加,我只需要在没有AddObject()方法的情况下调用SaveChanges(),因为它已经添加了。我尝试了这个,然后我没有异常,代码结束,但如果我检查数据库(SQL Server 2008 express),帐户根本没有添加。

这是我正在尝试的代码,我认为它应该可行,但很明显我错过了一些东西:

[TestMethod]
public void TestCreateNewAccount()
{
    try
    {
        AccountRepository accountRepository = new AccountRepository();

        Account account = new Account()
        {
            Username = "TestUsername",
            Password = "TestPassword",
            Email = "TestEmail",
            Nickname = "TestNickName",
            Quote = "Test Quote",
            AgreedToTermsDate = DateTime.Now,
            CreationDate = DateTime.Now,
            LastUpdateTime = DateTime.Now
        };

        // This works (all new entities!)
        //ConditionTerm conditionTerm = new ConditionTerm()
        //{
        //    Text = "This is some test condition term.",
        //    CreationDate = DateTime.Now,
        //    LastUpdateTime = DateTime.Now
        //};

        //This does not work (attaching an existing entity to a new one)
        ConditionTerm conditionTerm = new ConditionTermsRepository().GetCurrentTerm();

        Person person = new Person()
        {
            FirstName = "TestName",
            Surname = "TestSurname",
            CreationDate = DateTime.Now,
            LastUpdateTime = DateTime.Now
        };

        account.ConditionTerm = conditionTerm;
        account.Person = person;   

        using (ImproveEntities entities = Connection.GetModel())
        {
            if (account.ID > 0)
            {
                Account newAccount = new Account();
                newAccount.ID = account.ID;
                entities.Accounts.Attach(newAccount);
                entities.Accounts.ApplyCurrentValues(account);
            }

            else
            {
                entities.Accounts.AddObject(account);
                entities.SaveChanges();
            }
        }
    }

    catch (Exception)
    { 
    }
}

任何帮助都会非常苛刻!

编辑:这是GetCurrentTerm()方法:

    public ConditionTerm GetCurrentTerm()
    {
        using (ImproveEntities entities = Connection.GetModel())
        {
            ConditionTerm conditionTerm = (from ct in entities.ConditionTerms
                                           orderby ct.CreationDate descending
                                           select ct).FirstOrDefault();
            return conditionTerm;
        }
    }

1 个答案:

答案 0 :(得分:4)

如果我理解正确,您希望将新帐户与新用户一起插入数据库。但您不想创建新的ConditionTerm,而是将现有的ConditionTerm分配给该帐户。

问题是您在另一个上下文(在ConditionTerm中)中获取现有GetCurrentTerm,而不是用于保存新帐户的上下文。第二个上下文对ConditionTerm一无所知,所以你必须通过将它附加到第二个上下文来明确告诉这个conditionTerm已存在:

    // ...
    using (ImproveEntities entities = Connection.GetModel())
    {
        entities.ConditionTerms.Attach(conditionTerm);

        account.ConditionTerm = conditionTerm;
        account.Person = person;   

        entities.Accounts.AddObject(account);
        entities.SaveChanges();
    }
    // ...