使用 StudentVM
视图模型创建新的学生:
public StudentVM StudentVM { get; set; }//视图模型
var entry = _context.Add(new Student());
entry.CurrentValues.SetValues(StudentVM);//将视图StudentVM对应的属性值赋值到Student实例。
await _context.SaveChangesAsync();
SetValues 方法通过从另一个 PropertyValues 对象读取值来设置此对象的值。 SetValues
使用属性名称匹配。 视图模型类型:
- 无需与模型类型相关。
- 需要具有匹配的属性。
AsNoTracking 读取无需更新的数据(查询只读数据):
Student = await _context.Students
.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.AsNoTracking()
.FirstOrDefaultAsync(m => m.ID == id);
对于返回的实体不需要在当前上下文中更新的情况,AsNoTracking 方法将会提升性能。
读取一个实体的方法
生成的代码使用 FirstOrDefaultAsync 读取一个实体。 如果未找到任何内容,则此方法返回 NULL;否则,它将返回满足查询筛选条件的第一行。 FirstOrDefaultAsync
通常是比以下备选方案更好的选择:
- SingleOrDefaultAsync - 如果有多个满足查询筛选器的实体,则引发异常。 若要确定查询是否可以返回多行,
SingleOrDefaultAsync
会尝试提取多个行。 如果查询只能返回一个实体,就像它在搜索唯一键时一样,那么该额外工作是不必要的。 - FindAsync - 查找具有主键 ( PK) 的实体。 如果具有 PK 的实体正在由上下文跟踪,会返回该实体且不向数据库发出请求。 此方法经过优化,可查找单个实体,但无法通过
FindAsync
调用Include
。 如果需要相关数据,FirstOrDefaultAsync
则是更好的选择。
TryUpdateModelAsync 更新部分字段
var emptyStudent = new Student();
if (await TryUpdateModelAsync<Student>(
emptyStudent,
"student", // Prefix for form value.
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
{
_context.Students.Add(emptyStudent);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
- 仅更新列出的属性 (
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate
)。 - 查找带有“student”前缀的表单值。 例如
Student.FirstMidName
。 该自变量不区分大小写。
实体状态
数据库上下文会随时跟踪内存中的实体是否已与其在数据库中的对应行进行同步。 此跟踪信息可确定调用 SaveChangesAsync 后的行为。 例如,将新实体传递到 AddAsync 方法时,该实体的状态设置为 Added。 调用 SaveChangesAsync
时,数据库上下文会发出 SQL INSERT
命令。
实体可能处于以下状态之一:
-
Added
:数据库中尚不存在实体。SaveChanges
方法发出INSERT
语句。 -
Unchanged
:无需保存对该实体所做的任何更改。 从数据库中读取实体时,该实体具有此状态。 -
Modified
:已修改实体的部分或全部属性值。SaveChanges
方法发出UPDATE
语句。 -
Deleted
:已标记该实体进行删除。SaveChanges
方法发出DELETE
语句。 -
Detached
:数据库上下文未跟踪该实体。
在桌面应用中,通常会自动设置状态更改。 读取实体并执行更改后,实体状态自动更改为 Modified
。 调用 SaveChanges
会生成仅更新已更改属性的 SQL UPDATE
语句。
在 Web 应用中,读取实体并显示数据的 DbContext
将在页面呈现后进行处理。 调用页面 OnPostAsync
方法时,将发出具有 DbContext
的新实例的 Web 请求。 如果在这个新的上下文中重新读取实体,则会模拟桌面处理。