首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >操作后MVC3上未填充导航属性

操作后MVC3上未填充导航属性
EN

Stack Overflow用户
提问于 2012-08-16 23:09:02
回答 1查看 1.3K关注 0票数 0

我已经遇到这个问题两次了,我不太明白为什么。我通过发布一个视图模型在我的数据库中创建了一个葡萄酒。视图模型的Wine属性被正确填充,但是当我在db中保存更改时,导航属性并没有像我想象的那样被填充。我之所以需要这个,是因为我将这个wine对象传递给一个方法,以便将这些导航属性添加到我的搜索索引中。

我尝试用一个新变量重新查询数据库,但也不起作用。在这个问题上我真的很困惑--所以任何帮助都是很好的。我遇到了一个非常类似的问题,here没有收到任何答案。其他人已经通过重新查询db here解决了这个问题,但这对我不起作用。模型在GET请求上可以很好地填充,但在post请求上则不能。

控制器:

代码语言:javascript
运行
复制
[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);
}

ViewModel:

代码语言:javascript
运行
复制
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();
    }

}

型号:

代码语言:javascript
运行
复制
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; }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-17 05:00:39

该视图模型的Wine属性被正确填充,但是当我在数据库中保存更改时,导航属性并没有像我想象的那样被填充。

保存对数据库的更改永远不会从数据库加载数据,因此无法填充导航属性。在这种特定情况下,您期望的是,只要您访问导航属性(在模型中为virtual ),延迟加载就会将它们推向前进。这实际上是每个导航属性的单独查询。

现在,问题是延迟加载不能在POST操作中工作,因为模型绑定器已经实例化了nw.Wine实体。但是模型绑定器(它对实体框架一无所知)并没有为Wine实体创建延迟加载代理对象,而只是使用new (或者可能使用反射API进行一些实例化)。需要一个延迟加载代理才能使延迟加载工作。

如果您想手动创建nw.Wine实体,您可以使用以下命令创建延迟加载代理:

代码语言:javascript
运行
复制
nw.Wine = db.Wines.Create();

使用nw.Wine = new Wine();的...instead。然后,您的代码将如您所期望的那样工作,并且延迟加载将在您将实体附加/添加到EF上下文之后填充导航属性。

您在评论中提出的解决方案...

代码语言:javascript
运行
复制
nw.Wine.Producer = db.Producers.Find(nw.Wine.ProducerID)

...(其他导航属性也是如此)在我看来是正确的方式。或者,您可以使用显式加载:

代码语言:javascript
运行
复制
db.Entry(nw.Wine).Reference(w => w.Producer).Load();

但是这三种情况--惰性加载(如果可以),使用Find或者显式加载--都会执行相同的数据库查询。因此,在性能方面没有区别。

GET操作中的延迟加载之所以有效,是因为--我猜--您正在从DB加载wine实体……

代码语言:javascript
运行
复制
var wine = db.Wines.Find(id); // or maybe `Single` or `First`, etc.

从数据库加载实体的...and创建了一个惰性加载代理。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11990248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档