0

この問題に 2 回遭遇しましたが、その理由がよくわかりません。ビューモデルを投稿して、データベースにワインを作成しています。そのビューモデルの Wine プロパティは正しく入力されていますが、データベースに変更を保存すると、ナビゲーション プロパティが入力されません。これが必要なのは、このワイン オブジェクトをメソッドに渡して、これらのナビゲーション プロパティを検索インデックスに追加するためです。

データベースを新しい変数に再クエリしようとしましたが、それもうまくいきません。私はこれについて本当に混乱しています-だから、どんな助けも素晴らしいでしょう. 非常によく似た問題に遭遇し、ここで回答が得られませんでした。他の人はここでデータベースを再クエリすることでこれを解決しましたが、それは私にとってはうまくいきません。モデルは GET リクエストでは正常に読み込まれますが、投稿では読み込まれません。

コントローラ:

[HttpPost]
//[Authorize(Roles = "admin, producereditor")]
public ActionResult Create(NewWineViewModel nw)
{
    if (ModelState.IsValid)
    {
        nw.Wine.Active = nw.IsRequest ? false : true;
        //keep nullable for requests.
        nw.Wine.ImporterID = nw.Wine.ImporterID == 0 ? null : nw.Wine.ImporterID;
        nw.Wine.VarTypeID = nw.Wine.VarTypeID == 0 ? null : nw.Wine.VarTypeID;
        nw.Wine.OriginID = nw.Wine.OriginID == 0 ? null : nw.Wine.OriginID;
        nw.Wine.AppID = nw.Wine.AppID == 0 ? null : nw.Wine.AppID;
        nw.Wine.VintageID = nw.Wine.VintageID == 0 ? null : nw.Wine.VintageID;

        nw.Wine.CreatedBy = this.User.Identity.Name;
        nw.Wine.CreatedOn = DateTime.Now;
        db.Wines.Add(nw.Wine);

        db.SaveChanges();

        var wineToIndex = db.Wines.Find(nw.Wine.WineID);
       // nw.Wine.QRUrl = WineUtils.MakeQRCode(nw.Wine);
        //db.SaveChanges();


        //Lucene.LuceneSearch.AddUpdateLuceneIndex(db.Wines.Find(nw.Wine.WineID));


        if (nw.IsRequest)
        {
            nw.VOAVIRequest.WineID = nw.Wine.WineID;
            nw.VOAVIRequest.CreatedBy = User.Identity.Name;
            nw.VOAVIRequest.CreatedOn = DateTime.Now;
            db.VOAVIRequests.Add(nw.VOAVIRequest);
            db.SaveChanges();

            return RedirectToAction("Requested");

            //redirect to "Request Submitted" page for new wines
        }

        return RedirectToAction("Details", new { id = nw.Wine.WineID });
    }

    ViewBag.VarTypeID = new SelectList(db.VarTypes, "VarTypeID", "Name").Default("Select a Varietal/Type", nw.Wine.VarTypeID.ToString());
    ViewBag.OriginID = new SelectList(db.Origins, "OriginID", "Name").Default("Select an Origin", nw.Wine.OriginID.ToString());
    ViewBag.AppID = new SelectList(db.Apps, "AppID", "Name").Default("Select an Appellation", nw.Wine.AppID.ToString());
    ViewBag.VintageID = new SelectList(db.Vintages, "VintageID", "Name").Default("Select a Vintage", nw.Wine.VintageID.ToString());
    ViewBag.ImporterID = new SelectList(db.Importers, "ImporterID", "Name").Default("Select an Importer", nw.Wine.ImporterID.ToString());
    if (User.IsInRole("producer"))
    {
        Producer currentProd = db.ProducerUsers.Find(Membership.GetUser().ProviderUserKey).Producer;
        ViewBag.ProducerID = currentProd.ProducerID;
        ViewBag.ProducerName = currentProd.Name;
    }
    else
    {
        ViewBag.ProducerSelect = new SelectList(db.Producers, "ProducerID", "Name", nw.Wine.ProducerID);
    }
    return View(nw);
}

ビューモデル:

public class NewWineViewModel
{

    public Wine Wine { get; set; }
    public VOAVIRequest VOAVIRequest { get; set; }
    public bool IsRequest { get; set; }

    public SelectList VarTypes { get; set; }
    public SelectList Origins { get; set; }
    public SelectList Apps { get; set; }
    public SelectList Vintages { get; set; }
    public SelectList Importers { get; set; }

    public NewWineViewModel()
    {
        this.Wine = new Wine();
    }

}

モデル:

public class Wine :Updater
{
    public int WineID { get; set; }
    //public int WineTypeID { get; set; }
    [Display(Name = "Varietal/Type")]
    public int? VarTypeID { get; set; }
    [Display(Name = "Origin")]
    public int? OriginID { get; set; }
    [Display(Name = "Appellation")]
    public int? AppID { get; set; }
    [Display(Name = "Vintage")]
    public int? VintageID { get; set; }
    [Display(Name = "Importer")]
    public int? ImporterID { get; set; }
    public int ProducerID { get; set; }
    public string Designate { get; set; }
    [Display(Name = "Drink Window")]
    public string DrinkWindow { get; set; }
    public string Body { get; set; }
    public string SKU { get; set; }
    [Display(Name = "Varietal Makeup")]
    public string VarietalMakeup { get; set; }
    [Display(Name = "Case Production")]
    public string CaseProduction { get; set; }
    [Display(Name = "Alcohol Content")]
    public double? AlcoholContent { get; set; }
    public string Winemaker { get; set; }
    [Display(Name = "Consulting Winemaker")]
    public string ConsultWinemaker { get; set; }
    public bool Sustainable { get; set; }
    public bool Kosher { get; set; }
    public bool Organic { get; set; }
    public bool Biodynamic { get; set; }
    public bool SalmonSafe { get; set; }
    public Boolean Active { get; set; }
    [Display(Name = "ResidualSugar")]
    public double? RS { get; set; }
    public double? pH { get; set; }
    public string QRUrl { get; set; }


    public virtual WineType WineType { get; set; }

    public virtual VarType VarType { get; set; }
    public virtual Origin Origin { get; set; }
    public virtual App App { get; set; }
    public virtual Vintage Vintage { get; set; }
    public virtual Importer Importer { get; set; }
    public virtual Producer Producer { get; set; }

    [JsonIgnore]
    public virtual ICollection<POS> POSs { get; set; }
    [JsonIgnore]
    public virtual ICollection<Review> Reviews { get; set; }
    [JsonIgnore]
    public virtual ICollection<Doc> Docs { get; set; }

    [JsonIgnore]
    public IEnumerable<SelectListItem> BodyList { get; set; }
4

1 に答える 1

3

そのビューモデルの Wine プロパティは正しく入力されていますが、データベースに変更を保存すると、ナビゲーション プロパティが入力されません。

変更をデータベースに保存しても、DB からデータが読み込まれないため、ナビゲーション プロパティを設定できません。この特定のケースで予想されることは、遅延読み込みvirtualによって、アクセスするとすぐに(モデル内の) ナビゲーション プロパティが生成されることです。これは、実際にはナビゲーション プロパティごとに個別のクエリです。

問題は、モデル バインダーがnw.Wineエンティティをインスタンス化しているため、POST アクションで遅延読み込みが機能しないことです。しかし、モデル バインダー (Entity Framework について何も知らない) は、Wine エンティティの遅延読み込みプロキシ オブジェクトを作成せず、単にnew(またはリフレクション API を使用したインスタンス化を) 使用します。遅延読み込みを機能させるには、遅延読み込みプロキシが必要です。

エンティティを手動で作成する場合は、次をnw.Wine使用して遅延読み込みプロキシを作成できます...

nw.Wine = db.Wines.Create();

...使用する代わりにnw.Wine = new Wine();。コードは期待どおりに機能し、エンティティを EF コンテキストにアタッチ/追加した後、遅延読み込みによってナビゲーション プロパティが設定されます。

コメントで提案した解決策...

nw.Wine.Producer = db.Producers.Find(nw.Wine.ProducerID)

...(他のナビゲーション プロパティについても同様) は、私の意見では正しい方法です。または、明示的な読み込みを使用できます。

db.Entry(nw.Wine).Reference(w => w.Producer).Load();

ただし、遅延読み込み (機能する場合)、Find明示的読み込みの使用または使用の 3 つのケースすべてで、同じデータベース クエリが実行されます。したがって、パフォーマンスに関しては違いはありません。

GET アクションでの遅延読み込みが機能するのは、DB から wine エンティティを読み込んでいるからだと思います...

var wine = db.Wines.Find(id); // or maybe `Single` or `First`, etc.

...データベースからエンティティをロードすると、遅延ロード プロキシが作成されます。

于 2012-08-16T21:00:39.233 に答える