繁体   English   中英

null EF 中的相关数据对象

[英]Related data object in null EF

你好最近我将我的项目从核心 2.1 更新到 2.2,之后当从表单(编辑)发送一个带有子对象的对象时,会出现带有空值的对象(见下图),并且 ModelState.IsValid 总是假的,因为是验证子类中的空值,请帮助!

https://i.ibb.co/hsmpc43/Screen-Shot-2019-04-16-at-11-03-17-AM.png

这是我的课:

public class New : BaseEntity
{
    public string Title { get; set; }
    public string Message { get; set; }
    [ForeignKey("TowerID"), Display(Name = "Edificio")]
    public virtual Tower Tower { get; set; }
    public int TowerID { get; set; }

}

我的控制器:

[BreadCrumb(Title = "Editar", Order = 1)]
public IActionResult Edit(int id)
{
    var news = _newBL.GetById(id);
    PopulateDropDowns();
    return View(news);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(New value)
{
    if (ModelState.IsValid)
    {
        value.Resources = _files;
        await _newBL.Update(value);
        return RedirectToAction(nameof(Index));
    }
    PopulateDropDowns();
    return View(value);
}

和我的峰会形式:

<form asp-action="Edit" onsubmit="return disableButton(this);">

            <div class="form-row">
                <div class="form-group col-md-3">
                    <label asp-for="TowerID"></label>
                    <div class="custom-select">
                        <select asp-for="TowerID" class="form-control" asp-items="ViewBag.TowerID">
                            <option>Seleccione</option>
                        </select>

                    </div>
                    <span asp-validation-for="TowerID" class="text-red"></span>
                </div>
                <div class="form-group col-md-2">
                    <label asp-for="CreatedDate">Creado en</label>
                    <label asp-for="CreatedDate" class="input-readonly" readonly>@Model.CreatedDate</label>
                    <input type="hidden" asp-for="CreatedDate" />
                </div>
            </div>
            <div class="form-row">
                <div class="form-group col-md-12">
                    <label asp-for="Title"></label>
                    <input asp-for="Title" class="form-control" placeholder="@ViewData.ModelMetadata.Placeholder" />
                    <span asp-validation-for="Title" class="text-red"></span>
                </div>
            </div>
            <div class="form-row">
                <div class="form-group col-md-12">
                    <label asp-for="Message"></label>
                    <textarea id="summernote" asp-for="Message" class="form-control" rows="3"></textarea>
                    <span asp-validation-for="Message" class="text-red"></span>
                </div>
            </div>
            <div class="form-row">
                <button type="submit" class="btn green m-1" id="save"><i class="fas fa-save"></i> Guardar</button>
                <button asp-action="Index" type="submit" class="btn blue-darken-1 m-1"><i class="fa fa-arrow-left"></i> Atras</button>
                <a  class="btn red m-1" data-toggle="modal" data-target="#dangerModal">
                    <i class="fa fa-trash"></i> Eliminar
                </a>
            </div>
        </form>

这仅在我更新到核心 2.2 时开始发生,并且是当我发送带有新值的编辑表单时。

提前谢谢

更新:

我尝试改回核心 2.1 并工作,但是当我切换回 2.2 开始发生时,塔对象​​来自剃刀 POST 并带有所有空值,但新闻类型没有(见图)

好吧,您只是发布了Tower的 id,而且确实正在填充。 没有其他关于Tower被发布,所以当然所有其他属性都是 null 或默认值。 我不确定为什么你认为这只是在 2.2 中才开始发生,因为情况总是如此。 事实上,无论您使用什么框架,情况都会如此。 这可能是 Django 或 Ruby on Rails,并且Tower道具仍然全部为空,因为您没有发布它们中的任何一个。

HTTP 是一种无状态协议。 除了通过请求本身产生的东西之外,什么都不存在。 没有关于这些属性曾经是什么的记忆,因为甚至不知道先前提出过请求。 您可以在此处插入诸如会话之类的内容,但这本质上是假状态。 服务器存储与会话 id 关联的数据,然后通过 cookie 将该会话 id 传输到客户端。 然后,客户端必须在每个后续请求中传回包含会话 ID 的 cookie 以恢复会话。 即便如此,数据本质上仍然是请求的一部分,它只是作为特定保存的服务器端数据集的标识符而不是整个数据集的标识符。

无论如何,这很容易解决,只需对您的代码进行一些调整即可。 首先,永远不要直接绑定到实体类。 造成这种情况的原因有很多,但一个主要问题是过度发布。 使用您现在拥有的代码,客户端可以更改发送的数据以更改实体的 id 之类的内容,并且您最终会使用id 修改实体,而不是实际正在编辑的实体。 与此相关的另一条规则是,出于许多相同的原因,您不应直接保存用户发布的任何内容。

相反,您应该绑定到一个视图模型,并且该视图模型应该只包含您实际希望允许用户编辑的属性。 然后,您从数据库中获取新的实体并将视图模型中发布的值映射到它上,最后保存实体。

public async Task<IActionResult> Edit(NewViewModel value)
{
    if (!ModelState.IsValid)
    {
        PopulateDropDowns();
        return View(value);            
    }

    var entity = await _newBL.GetById(id);
    if (entity == null)
        return NotFound();

    entity.Title = value.Title;
    entity.Message = value.Message;
    entity.TowerID = value.TowerID;
    entity.Resources = _files;

    await _newBL.Update(entity);
    return RedirectToAction(nameof(Index));
}

如果您愿意,可以使用像 AutoMapper 这样的库来处理映射部分。

要解决此问题,您需要在 GetById() 中添加相关数据( Children ),方法是在您的函数中添加类似这样的内容.Include(blog => blog.Posts)
文档: https : //docs.microsoft.com/en-us/ef/core/querying/related-data
或者您需要激活延迟加载(默认情况下延迟加载被禁用)
查看更多: https : //www.learnentityframeworkcore.com/lazy-loading

更新 :
在模型为空的情况下,您需要为所有模型项添加一个隐藏输入,以在提交表单时保存它们的值。
例子 :
<input type="hidden" asp-for="Tower.Id" />

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM