Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 查看模型虚拟属性和下拉列表_C#_Asp.net Mvc_Entity Framework - Fatal编程技术网

C# 查看模型虚拟属性和下拉列表

C# 查看模型虚拟属性和下拉列表,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,我很难掌握正确的方法来创建视图模型并使用Entity Framework将信息保存回数据库,而且我似乎找不到我要查找的信息,因此如果我忽略了它,请原谅我 我看到这篇帖子,他似乎在问同样的问题,但没有得到答案 我的主要问题是, 出于编辑目的,如果我有一个产品模型具有保修模型关系,我是应该在视图模型中使用虚拟财产保修,还是应该使用int保修ID? 如果我应该使用虚拟财产,为什么此代码不能正确保存保修? 我是否需要明确标记或填充保修以进行更新? 请注意,这不会按预期填充我的编辑视图和选择列表 我的(简

我很难掌握正确的方法来创建视图模型并使用Entity Framework将信息保存回数据库,而且我似乎找不到我要查找的信息,因此如果我忽略了它,请原谅我

我看到这篇帖子,他似乎在问同样的问题,但没有得到答案

我的主要问题是,

出于编辑目的,如果我有一个
产品模型
具有
保修模型
关系,我是应该在视图模型中使用
虚拟财产保修
,还是应该使用
int保修ID

如果我应该使用虚拟财产,为什么此代码不能正确保存
保修

我是否需要明确标记或填充保修以进行更新?

请注意,这不会按预期填充我的编辑视图和选择列表

我的(简化)代码设置如下:

型号:

    public int ModelId{ get; set; }

    public int ModelNumber { get; set; }

    public virtual Warranty Warranty { get; set;}
视图模型:

    public int ModelId { get; set; }

    [Required(ErrorMessage = "Model Number required")]
    [StringLength(25, ErrorMessage = "Must be under 25 characters")]
    [Display(Name="Model Number")]
    public string ModelNumber { get; set; }

    //related objects and necesary properties
    public virtual Warranty Warranty { get; set; }

    public IEnumerable<SelectListItem> WarrantySelectListItems { get; set; }
主计长(职位)(在建工程):

视图(简化):


@标签(“保修”,新的{@class=“控制标签col-md-2”})
@Html.DropDownListFor(x=>x.Warranty.WarrantyId,Model.Warranty选择列表项,“--Select-->”)
@Html.ValidationMessageFor(model=>model.Warranty.WarrantyId)
同样,我只想知道设置这些viewmodels和models的正确/最佳方法,以便EF尽可能多地完成工作我觉得如果我必须创建一个
保修ID
字段,我是做错了什么,但可能不是这样。


提前谢谢。非常感谢您提供的任何见解/帮助。

您的视图模型中必须有int-WarrantyId。 比你认为的要好

@Html.DropDownListFor(x => x.WarrantyId, Model.WarrantySelectListItems, "--Select--")

在控制器(POST)中,获取保修ID(从下拉列表中选择)并从数据库中查找对象(var保修=db.warranty.Where(w=>w.WarrantyId==editModel.WarrantyId或类似的内容),然后将该对象分配给modelEntity。

视图模型中必须有int-WarrantyId。 比你认为的要好

@Html.DropDownListFor(x => x.WarrantyId, Model.WarrantySelectListItems, "--Select--")

在控制器(POST)中,获取保修ID(从下拉列表中选择)并从数据库中查找对象(var保修=db.warranty.Where(w=>w.WarrantyId==editModel.WarrantyId或类似的内容),然后将该对象分配给modelEntity。

您处理的肯定是导航属性(模型类上的虚拟属性),这很好地解释了它们:

定义这些的难点在于如何为数据库设置DbContext。官方文档如下:

简单的父子关系非常容易处理,还有一些情况(更复杂),您可以定义一些物理上来自表中同一行的模型,但我认为您在这里没有处理这些问题

MVC部分是一个独立的关注点,理想情况下您应该这样对待它。控制器代码应该只委托真正的“工作”工作单元模式,如果你选择使用它的话,在你遇到需要跨多个表或实体集持久化/编辑大量内容的情况时才是真正必要的,因为你可能希望它作为一个整体失败或成功。如果你只是在处理单个对象的简单持久化,不要这样做甚至使用工作单元模式使其复杂化


EF或任何ORM框架需要记住的另一件事是,它需要跟踪更改或与现有记录进行比较,因此当您完成此操作时,键值变得非常重要。

您处理的肯定是导航属性(模型类上的虚拟属性),这很好地解释了它们:

定义这些的难点在于如何为数据库设置DbContext。官方文档如下:

简单的父子关系非常容易处理,还有一些情况(更复杂),您可以定义一些物理上来自表中同一行的模型,但我认为您在这里没有处理这些问题

MVC部分是一个独立的关注点,理想情况下您应该这样对待它。控制器代码应该只委托真正的“工作”工作单元模式,如果你选择使用它的话,在你遇到需要跨多个表或实体集持久化/编辑大量内容的情况时才是真正必要的,因为你可能希望它作为一个整体失败或成功。如果你只是在处理单个对象的简单持久化,不要这样做甚至使用工作单元模式使其复杂化

EF或任何ORM框架需要记住的另一件事是,它需要跟踪更改或与现有记录进行比较,因此当您完成此项工作时,键值变得非常重要

出于编辑目的,如果我有一个ProductModel模型 保修模型关系,我应该使用虚拟财产吗 视图模型中的保修,还是我应该使用int保修ID

对于
ViewModel
的属性,不能使用
virtual
关键字,因为
ViewModel
与实体框架无关。 使用
virtual
关键字的原因是允许在实体框架中延迟加载 在产品POCO类中的保修导航属性中,您可以访问保修属性,如下所示:

Model.Warranty.WarrantyId
    public class Product
    {
        public int ModelId { get; set; }
        public int ModelNumber { get; set; }
        public int WarrantyId {get;set;}

        [ForeignKey("WarrantyId ")]
        public virtual Warranty Warranty { get; set; }
    }
它没有将保修信息保存到数据库中的原因是,您需要在产品类中定义保修外键属性

在您的情况下,如果您使用的是代码优先的方法,并且产品是您的POCO类,只需将其保持如下所示:

Model.Warranty.WarrantyId
    public class Product
    {
        public int ModelId { get; set; }
        public int ModelNumber { get; set; }
        public int WarrantyId {get;set;}

        [ForeignKey("WarrantyId ")]
        public virtual Warranty Warranty { get; set; }
    }
然后,您的ViewModel:

    public class MyViewModel 
    {
        public Product Product { get; set; }
        public IEnumerable<SelectListItem> WarrantySelectListItems { get; set; }
    }
O
  @model MyViewModel

  @Html.DropDownList("Product.Warranty.WarrantyId", Model.WarrantySelectListItems, "--Select--")
  @Html.ValidationMessageFor("Product.Warranty.WarrantyId")
public class ViewAViewModel
{
    [Required]
    public int WarrantyId { get; set; }
}

public class ViewBViewModel
{
    // No longer required.
    public int WarrantyId { get; set; }
}
public IEnumerable<SelectListItem> WarrantySelectListItems { get; set; }
public int ModelId { get; set; }

// Removed for clarity, include needed properties in the UI

public int WarrantyId { get; set; }

public IEnumerable<SelectListItem> WarrantySelectListItems { get; set; }
public ActionResult Edit(int? id)
{
    //check the id
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    //get the model and make sure the object is populated
    var model = _modelService.GetModel(id.Value);
    if (model == null)
    {
        return HttpNotFound();
    }

    //pass our entity (db) model to our view model
    var editViewModel = new EditViewModel();
    editViewModel.InjectFrom(model);

    // You could instead create a custom injection like FlatLoopValueInjection
    // That would flatten and remove duplicates from 
    // Model.Warranty.WarrantyId to ViewModel.WarrantyId
    editViewModel.WarrantyId = model.Warranty.Id;

    //warranty select list
    editViewModel.WarrantySelectListItems = WarrantySelectList(editViewModel.WarrantyId);

    return View(editViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditViewModel editViewModel)
{
    if (!ModelState.IsValid)
    {
        return View(editViewModel);
    }

    // You need to reconstruct the model itself, there are faster ways but I wanted
    // to showcase the logic behind it
    // I didn't do any null check or anything to simplify

    // Load the model used from the database
    var modelEntity = _modelService.GetModel(editViewModel.ModelId);

    // You can do an InjectFrom for the other properties you need
    // with custom Injection to unflatten
    modelEntity.InjectFrom(editViewModel);

    // Load the selected warranty from the database
    var warrantyEntity = _warrantyService.GetWarranty(editViewModel.WarrantyId);

    // Update the warranty of the model with the one loaded
    modelEntity.Warranty = warrantyEntity;

    _modelService.Update(modelEntity);

    _unitOfWork.Save();

    return RedirectToAction("Index");
}
<div class="form-group">
    @Html.Label("Warranty", new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownListFor(x => x.WarrantyId, Model.WarrantySelectListItems, "--Select--")
        @Html.ValidationMessageFor(model => model.WarrantyId)
    </div>
</div>
Model.Warranty.Id => (flatten) => Model.WarrantyId => (unflatten) => Model.Warranty.Id