EFに関して見つかった類似の投稿をすべて読んでいますが、解決策を見つけることができません。EF SaveChanges()が例外をスローする 'プロパティの現在の値がnullの場合にのみEntityKeyプロパティを設定できます'
私はEFの新機能で、作業に役立つ情報をいくつか読んできましたが、何か不足していると思います。
シナリオは、このようなものです:
私は、ユーザーがASP.NET Webページでアカウントを作成することができるようにしたいです。だから私は 'アカウント'というテーブルを持っています。ユーザーはサイトの条件条項に同意しなければなりません。これはFutereで更新される可能性があります。したがって、アカウントと1対多の関係を持つ「ConditionTerms」という表があります(多くのアカウントには固有の条件項があります)。
アカウントのデータから特定の個人ユーザーデータを分離したいので、私は「Persons」というテーブルも作成しました。私は、関係者が多くのアカウントを持つように関係船を設定しました。
今、データベースにアカウントを保存する場合、データベースで使用可能な最後の条件を取得し、アカウントエンティティに追加します。その後、SaveChanges()を介してデータを保存しようとすると、投稿のタイトルに例外が表示されます。問題は、すべてのエンティティが新しい場合、関連付けが作成されると、すべてのアイテムのEntityStateが「デタッチ」され、機能しますが、既存の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)
{
}
}
すべてのヘルプは非常にapreciatedされるだろう!
EDIT:これは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;
}
}
?私は 'GetCurrentTerm'がそれ自身のコンテキストを使用し、' using'が第2のコンテキストを作成すると思います。 'GetCurrentTerm'のコンテキストが破棄されているか、または' conditionTerm'がこのコンテキストに引き続き接続されていますか? 'GetCurrentTerm'のコードを表示できますか?そして、私たちは 'else'ブロックについてのみ話していますか?あなたのAccountのIDが何らかの値に設定されていない限り、 'account.ID'がいつあなたのコードで0よりも大きいことがわかりません。 – Slauma
こんにちはスラマ! GetCurrentTerm()メソッドのコードを追加しました。私はどこかで、使用節でコンテキストを使用するのが一般的なベストプラクティスであると読むので、常に最後に配置されるようにします。そこに何か問題はありますか? elseメソッドはテストメソッドではあまり意味がありませんが、SaveAccount()メソッドで新しいアカウントや既に存在するものを渡すことができます(私はそれを更新できます)。 –
申し訳ありませんが、私は 'if'ブロックを意味しました。私が新しいアカウントを追加しようとしている瞬間に、私はアップデートでさらに詳しく説明します。 –