0

コントローラでデータを編集する際に問題が発生しました。私の2つのモデルは次のようになります。

[Table("Zielgruppen")]
public class Zielgruppe
{
    public int Id { get; set; }
    public string Zielgruppenname { get; set; }
    public Bezug Bezug { get; set; }
}

public class Bezug
{
    public int Id { get; set; }
    public string Bezugsname { get; set; }
}

私のコントローラーの機能は次のとおりです。

public ActionResult Edit(int id)
{
    Zielgruppe zielgruppe = _db.Zielgruppe.Include("Bezug").Single(z => z.Id == id);
    ViewBag.BezugsId = new SelectList(_db.Bezug, "Id", "Bezugsname", zielgruppe.Bezug.Id);
    return View(zielgruppe);
}

[HttpPost]
public ActionResult Edit(Zielgruppe aktualisierteZielgruppe)
{
    if(ModelState.IsValid)
    {
        aktualisierteZielgruppe.Bezug = _db.Bezug.Find(aktualisierteZielgruppe.Bezug.Id);
        _db.Entry(aktualisierteZielgruppe).State = EntityState.Modified;
        _db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.BezugsId = new SelectList(_db.Bezug, "Id", "Bezugsname", aktualisierteZielgruppe.Bezug.Id);
    return View();            
}

私の問題は、aktualisierteZielgruppe.Bezugを変更すると、変更がデータベースに保存されないことです。

これは私のedit.cshtmlです:

@model Medien_Archiv.Models.Zielgruppe

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Zielgruppe</legend>

        @Html.HiddenFor(model => model.Id)

        <div class="editor-label">
            @Html.LabelFor(model => model.Zielgruppenname)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Zielgruppenname)
            @Html.ValidationMessageFor(model => model.Zielgruppenname)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Bezug)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.Bezug.Id, ViewBag.BezugsId as SelectList)   
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
4

4 に答える 4

1

コードからはわかりにくいですが、ビューから返された ID に基づいてデータベースからオブジェクトをロードし、State を Modified に設定してから、同じオブジェクトを保存しているようです。

データベースに保存する前に、実際にビューからオブジェクトにプロパティを設定しているようには見えません。どのORMを使用していますか?ほとんどの ORM は、各プロパティが変更されたときにオブジェクトの State を処理し、コミットされたときに独自の状態を Modified に設定します。

データベースからオブジェクトをロードする前にブレークポイントを設定し、ビューから返される値をすばやく監視し、データベースからロードした後に再度それらをすばやく監視すると、それらが上書きされたことに気付くと思います

于 2012-03-13T14:21:37.790 に答える
0

これは、エンティティ フレームワークが失敗するケースの 1 つで、更新された関連付けを追跡します。

ここでは、派手なモデル バインディング (つまり、データベースからのモデル バインダーのプル) を行っていないことを前提としています。

if(ModelState.IsValid)
{
    aktualisierteZielgruppe.Bezug = _db.Bezug.Find(aktualisierteZielgruppe.Bezug.Id);

    // The problem is here.  EF doesn't mark associations as modified
    // the same way it tracks scalar types.
    _db.Entry(aktualisierteZielgruppe).State = EntityState.Modified;
    _db.SaveChanges();
    return RedirectToAction("Index");
}

より一般的な方法は次のとおりです。

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    // Get the original record to edit from the database.
    var gruppe = _db.Zielgruppe.Include("Bezug").Single(z => z.Id == id);

    // This will attempt to do the model binding and map all the submitted 
    // properties to the attached entity.
    if (TryUpdateModel(grupppe))
    {
        _db.SaveChanges();
        return RedirectToAction("Index");
    }
}

また、エンティティにバインドするこの方法では、オーバーポスティング攻撃を受けやすくなることにも注意してください。 モデル バインド中にモデル プロパティをホワイトリストに登録するか、ビュー モデルにバインドしてからマップすることで、この攻撃ベクトルを軽減できます。

于 2012-03-13T15:12:46.400 に答える
0

上記の例のいずれかのように FormCollection を渡す場合、次のように、その値を変更してから、TryUpdateModel() を呼び出す前に FormCollection を ValueProvider に再割り当てできます。

this.ValueProvider = collection.ToValueProvider();

ただし、Zielgruppe のようなオブジェクトを渡している場合は、わかりません。自分でそれを理解しようとしています。

于 2012-08-13T14:21:24.033 に答える