3

1 対 1 の関係にある 2 つのモデル クラスがあります。

class Person
{
    public int PersonID { get; set; }
    public int DetailPersonID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DetailPerson DetailPerson { get; set; }
}

class DetailPerson
{
    public int DetailPersonID { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
}

および編集ページ ビューのコード:

@using (Html.BeginForm())
{
    @Html.HiddenFor(m => m.PersonID)

    @Html.LabelFor(m => m.FirstName)
    @Html.TextBoxFor(m => m.FirstName)

    @Html.LabelFor(m => m.LastName)
    @Html.TextBoxFor(m => m.LastName)

    @Html.LabelFor(m => m.DetailPerson.Address)
    @Html.TextBoxFor(m => m.DetailPerson.Address)

    @Html.LabelFor(m => m.DetailPerson.PhoneNumber)
    @Html.TextBoxFor(m => m.DetailPerson.PhoneNumber)

    <input type="submit" value="Edit">

}

EF スキャフォールドは、次のコードを使用してデータを更新します。

db.Entry(person).State = System.Data.EntityState.Modified;
db.saveChanges();

編集フォームを送信すると、次のようなエラーが発生しました。

対応する主キー値が存在しないため、外部キー値を挿入できません。[ 外部キー制約名 = FK_dbo.People_dbo.DetailPersons_DetailPersonID ]

しかし、私がこれを行うと:

Person p = db.Persons.Find(person.PersonID);
p.DetailPerson = person.DetailPerson;
p.FirstName = person.FirstName;
p.LastName = person.LastName;
db.saveChanges();

エラーなしでデータの更新に成功

EntityState.Modifiedを含む行にブレークポイントを設定すると、最初の方法でエラーが発生する理由を知りたいのですが、外部キーの値 ( DetailPersonID ) は 0 です。次に、 @ Html.HiddenFor(m => m.編集フォームのDetailPersonID)

別のエラーが発生しました:

参照整合性制約違反が発生しました: 参照制約を定義するプロパティ値が、リレーションシップ内のプリンシパル オブジェクトと従属オブジェクトの間で一貫していません。

私はまだ別の方法でデータベースを更新していますが、データを更新するための EF 標準である最初の方法でエラーが発生した理由が気になります。

4

1 に答える 1

0

とにかくEFはデータベースを対応する形式に正規化するため、1対1の関係がある場合は2つのクラスを使用しないでください。このようにクラスを組み合わせます。

public class Person
{
    public int PersonID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
}

別のクラスが必要な場合 (推奨されません)、次のようにします。

public class Person
{
    public int PersonID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int DetailPersonID { get; set; }
    public virtual DetailPerson DetailPerson { get; set; }
}

public class DetailPerson
{
    public int PersonID { get; set; }
    public virtual Person Person { get; set; }
    public int DetailPersonID { get; set; }
    public string Address { get; set; }
    public string PhoneNumber { get; set; }
}

次に、オブジェクトを取得するときは、次のようにします。

// include the detail when retrieving the parent
Person person = db.People.Include(p=>p.DetailPerson).Single(p=>p.PersonId == whateverIdYou Need);

// modify whatever you like
person.DetailPerson.Address = "my new address";

// then your previous statement will work
db.Entry(person).State = System.Data.EntityState.Modified;
db.saveChanges();
于 2013-03-26T19:16:29.313 に答える