1

私はMVC4とEF5のコードファーストを使用しています。外部キーを持つ行を参照して新しいデータレコードを作成するときに、外部キー行のフィールドがnullに設定されるという問題があります。

簡略化したシナリオは次のとおりです。

public class Person
{
  string name { get; set; }
  Color color { get; set; }
}

public class Color
{
  int id { get; set; }
  string name { get; set; }
}

ビューモデル:

public class PersonViewModel
{
    public Person Person { get; set; }
    public IEnumerable<SelectListItem> Colors { get; set; }

    public PersonViewModel()
    {
        Context db = new Context();
        Colors = db.Colors.ToList().Select(t => new SelectListItem() { Text = t.Name, Value = t.Id.ToString() });
    }
}

コントローラー:

public ActionResult Create()
{
    return View(new PersonViewModel);
}

[HttpPost]
public ActionResult Create(PersonViewModel personViewModel)
{
    if (ModelState.IsValid)
    {   
        db.Person.Add(personViewModel.Person);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(personViewModel);
}

そして最後に、ビューの作成:

@model PersonViewModel
@using (Html.BeginForm())
{   
    @Html.ValidationSummary(true)

    @Html.LabelFor(model => model.Person.Name) 
    @Html.EditorFor(model =>  model.Person.Name)

    @Html.LabelFor(model => model.Person.Color)
    @Html.DropDownListFor(model => model.Person.Color.Id, this.Model.Colors)

    <input type="submit" value="Create" title="Create ticket" />
}

データに2つの色があるとします:1。赤2.青

ビューから新しい人物を作成し、色として青を選択すると、人物は正しく作成されますが、カラーテーブルのID 2の「青」はID(2)を維持しますが、名前は空に設定されます。

ここで拘束力のある問題が発生していると思いますか?これはフレームワークで標準としてサポートされるべきですか、それとも独自のモデルバインダーを作成する必要がありますか?

ありがとう

4

4 に答える 4

1

そのため、エンティティ フレームワークの規則に正しく従っていなかったことがわかりました。外部キー列を明示的に定義することで、エンティティ フレームワークは関係を正しく認識し、期待どおりに動作します。したがって、新しいデータ モデル (明示的な外部キー列の追加)

public class Person
{
  string Name { get; set; }

  int ColorId { get; set; }     
  Color color { get; set; }
}

public class Color
{
  int ColorId { get; set; }
  string name { get; set; }
}

および更新されたビュー (新しい外部キー列へのバインド):

@model PersonViewModel
@using (Html.BeginForm())
{   
    @Html.ValidationSummary(true)

    @Html.LabelFor(model => model.Person.Name) 
    @Html.EditorFor(model =>  model.Person.Name)

    @Html.LabelFor(model => model.Person.Color)
    @Html.DropDownListFor(model => model.Person.ColorId, this.Model.Colors)

    <input type="submit" value="Create" title="Create ticket" />
}
于 2012-10-09T20:57:31.467 に答える
1

ドロップダウンリストがその値をコントローラーに投稿すると、名前ではなく値のみが投稿されます。したがって、名前をバインドすることはできません。

値を検索するか、名前と値を含む値を作成し、ポストバックで解析して 2 つを分離する必要があります (「2:Blue」の値があり、string.Split を実行する場合があります)。 () ポストバックで。

于 2012-10-07T21:26:38.543 に答える
1

EF 5 を使用していることは知っていますが、EF 6 では、これらのナビゲーション プロパティを「仮想」として宣言し、DataAnnotations を使用して外部キーをマークする必要があります。

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public class Person
{
    public string Name { get; set; }
    public int ColorId { get; set; }  

    [ForeignKey("ColorId")]
    public virtual Color color { get; set; }
}

public class Color
{
    int ColorId { get; set; }
    string name { get; set; }
}

多くの色がある場合は、次の 2 行を の中に追加する必要がありますpublic class Person

public Person
{
    Colors = new HashSet<Color>();
}

public virtual ICollection<Color> Colors { get; set; }

これにより、ビューのモデルが の代わりに をPerson使用して、 をmodel.color.name介して色を呼び出すことができます。(ビューモデルを使用する必要がない場合、ビューモデルよりもエンティティ モデル自体を使用することを好むのは、このような理由からです。)PersonPersonViewModel

于 2015-03-18T03:01:55.893 に答える
0

投稿内で、model.Person.Color が id が正しく設定された新しい Color インスタンスとして設定されていることがわかります。標準モデル バインダーはその役割を果たしましたが、事実上、それをデータベースの何かに関連付けたいと考えています。

メモリから、外部キー属性が欠落しているか、流暢な API を使用して設定されている可能性があります。

最も簡単なオプションは、db.Color.Find( model.Person.Color.Id) を実行し、それを model.Person.Color に割り当てることです。

これには、参照チェックを実行して、存在しない色の Id を使用して post 値を挿入することで不正行為を行っていないことを確認するという追加の利点もあります。

于 2012-10-07T21:01:37.973 に答える