Sql server 使用实体框架更新后,Datetime默认值为null

Sql server 使用实体框架更新后,Datetime默认值为null,sql-server,asp.net-mvc,entity-framework,scaffolding,Sql Server,Asp.net Mvc,Entity Framework,Scaffolding,我有一个带有日期时间默认字段的表 使用脚手架为控制器+视图生成类和实体。 默认CRUD工作正常,但若我尝试更新寄存器,[DtOccurrence]在数据库中获取NULL 如何修复它?提前谢谢 创建并保存OK 仅更新[Name]字段为数据库发送空[DtOccurrence],我的自动生成类没有此[DtOccurrence]字段: 更新: 控制器创建方法 [HttpPost] [ValidateAntiForgeryToken] public async Task<IA

我有一个带有日期时间默认字段的表

使用脚手架为控制器+视图生成类和实体。 默认CRUD工作正常,但若我尝试更新寄存器,[DtOccurrence]在数据库中获取NULL

如何修复它?提前谢谢

创建并保存OK

仅更新[Name]字段为数据库发送空[DtOccurrence],我的自动生成类没有此[DtOccurrence]字段:

更新: 控制器创建方法

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Id,Name")] People people)
    {
        if (ModelState.IsValid)
        {
                _context.Add(people);
                await _context.SaveChangesAsync();

                return RedirectToAction("Edit", "Pessoas", new { people.Id });
        }
        return View(people);
    }

正如我在评论中提到的,虽然您向视图提供数据的初始请求是从DB上下文中获得的一个实体,但在更新方法中返回的对象不是同一个实体,并且与DbContext没有关联。它是一个反序列化副本。在不包含所有字段时调用Update将导致字段设置为null。从客户端调用这样一个独立的实体更新也是一个攻击未经授权更新到您域的攻击向量。调试工具/插件可以拦截对服务器的调用,并以多种方式更改实体数据

public async Task<IActionResult> Edit(int id, [Bind("Id,Name,")] People people)
{
    if (!ModelState.IsValid)
        return View(people);

    var dataPeople = await _context.People.SingleAsync(x => x.id == people.id);
    dataPeople.name = people.name;
    await _context.SaveChangesAsync(); // dataPeople is a tracked entity and will be saved, not people which is acting as a viewmodel.
    return RedirectToAction(nameof(Index));
}
使用Update将生成一个Update语句,其中覆盖实体上的所有字段。您可以决定将不完整的实体传递给视图,或从视图返回不完整的实体,但EF不知道缺少哪些数据,因为这些数据没有提供/更改,而清除了哪些数据,因此它会更新所有内容。相反,您应该根据提供的ID从DbContext加载实体,如果找不到ID,则会出错,然后在调用SaveChanges之前设置要更改的跟踪实体的属性。这样可以确保生成的SQL update语句只包含要更改的列

作为一般规则,我建议使用视图模型类在服务器和客户端之间进行模型通信,这样就可以清楚地知道传递的数据实际上是什么。在服务器和视图之间传递实体是一种反模式,容易出现性能问题、序列化问题以及有意和无意的数据损坏


其他验证应包括确保更改是完整的/合法的,并可能检查传递的模型和从DB加载的数据之间的行版本或上次修改日期,以确保它们匹配。当用户打开页面时,他们可能已获得记录的版本1。当他们最终提交表单时,如果DB返回版本2,则表示当时有人修改了该行。否则将覆盖更改

如何插入值?默认值仅在未传递任何值的情况下使用,因此如果传递NULL,它将填充NULL。@Larnu立即使用控制器方法更新添加的控制器方法是创建的,而不是更新的。\此问题通常是由于将仅部分完成的实体从视图传递回,仅包含视图更改的更新字段,然后将这些字段附加到上下文并保存它们而引起的。当EF执行更新或Attach+State=MODIFED时,它不知道更新了哪些字段,所以它会更新所有字段。@StevePy Sry,friend。现在用编辑方法更新。
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, [Bind("Id,Name,")] People people)
    {
        if (id != people.Id)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            try
            {
                _context.Update(people);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!PeopleExists(people.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return RedirectToAction(nameof(Index));
        }

        return View(people);
    }
public partial class Pessoa
{
    public Pessoa()
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}
public async Task<IActionResult> Edit(int id, [Bind("Id,Name,")] People people)
{
    if (!ModelState.IsValid)
        return View(people);

    var dataPeople = await _context.People.SingleAsync(x => x.id == people.id);
    dataPeople.name = people.name;
    await _context.SaveChangesAsync(); // dataPeople is a tracked entity and will be saved, not people which is acting as a viewmodel.
    return RedirectToAction(nameof(Index));
}