c# – 如何将计算值添加到此TryUpdateModelAsync <>中
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 如何将计算值添加到此TryUpdateModelAsync <>中,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4974字,纯文字阅读大概需要8分钟。
内容图文
我有以下代码:
if (await TryUpdateModelAsync<Host>(
hostToUpdate,
"Host",
s => s.Name, s => s.Description, s => s.Address, s => s.Postcode, s => s.Suburb,
s => s.State))
{
try
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (Host)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, "Unable to save. " +
"The host was deleted by another user.");
return Page();
}
var dbValues = (Host)databaseEntry.ToObject();
await setDbErrorMessage(dbValues, clientValues, _context);
// Save the current RowVersion so next postback
// matches unless an new concurrency issue happens.
Host.RowVersion = (byte[])dbValues.RowVersion;
// Must clear the model error for the next postback.
ModelState.Remove("Host.RowVersion");
}
}
我有一个名为Host的属性:LastDateModified和LastModified,它是计算/预定义值
即LastDateModified的DateTime.Now和LastDateModifiedBy的_userManager.GetUserId(User).
那么如何将此传递给此代码?
await TryUpdateModelAsync<Host>(
hostToUpdate,
"Host",
s => s.Name, s => s.Description, s => s.Address, s => s.Postcode, s => s.Suburb,
s => s.State)
解决方法:
您可以在保存对象之前设置(替代)值:
var hostToUpdate = await _context.Host.FindAsync(s => s.Id == id);
if (await TryUpdateModelAsync(
hostToUpdate,
"host", // empty with MVC
s => s.Name, s => s.Description, s => s.Address,
s => s.Postcode, s => s.Suburb, s => s.State))
{
try
{
hostToUpdate.LastModified = DateTime.Now;
hostToUpdate.LastDateModifiedBy = _userManager.GetUserId(User);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
// ...
}
请注意,LastModified和LastDateModifiedBy不是TryUpdateModelAsync语句的一部分.但如果是,那么这些价值将被行动所覆盖.
来自Razor Pages documentation:
The DB context keeps track of whether entities in memory are in sync
with their corresponding rows in the DB. The DB context sync
information determines what happens when SaveChangesAsync is called.
来自Mvc documentation(不再更新):
The Entity Framework’s automatic change tracking sets the Modified
flag on the fields that are changed by form input. When the
SaveChanges method is called, the Entity Framework creates SQL
statements to update the database row.
要解释其原因,首先TryUpdateModelAsync会更新用户更新的字段,然后操作会更新其他字段.所有都由实体框架跟踪和保存.这是默认的Entity Framework行为.
作为旁注,您可以选择添加自动更新字段的代码.在这种情况下,您不能忘记设置它们并保存几行代码.而且您根本不需要更改代码.
策略是实体实现基本字段并在保存更改时更新它们.这是一个更加扩展的版本:
public interface IBaseEntity
{
DateTime LastDateModified { get; set; }
string LastDateModifiedBy { get; set; }
DateTime DateCreated { get; set; }
string DateCreatedBy { get; set; }
}
public class Host : IBaseEntity
{
// the other fields
// ...
public DateTime LastDateModified { get; set; }
public string LastDateModifiedBy { get; set; }
public DateTime DateCreated { get; set; }
public string DateCreatedBy { get; set; }
}
上下文:
public partial class MyContext : DbContext
{
// Reference to the name of the current user.
private readonly string _userName;
public MyContext(DbContextOptions<MyContext> options, IHttpContextAccessor httpContext)
: base(options)
{
// Save the name of the current user so MyContext knows
// who it is. The advantage is that you won't need to lookup
// the User on each save changes.
_userName = httpContext.HttpContext.User.Identity.Name;
}
public virtual DbSet<Host> Host { get; set; }
// You'll only need to override this, unless you are
// also using non-async SaveChanges.
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
UpdateEntries();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
// You can move this to another partial class.
private void UpdateEntries()
{
// Modified
var modified = ChangeTracker.Entries().Where(v => v.State == EntityState.Modified && typeof(IBaseEntity).IsAssignableFrom(v.Entity.GetType())).ToList();
modified.ForEach(entry =>
{
((IBaseEntity)entry.Entity).LastDateModified = DateTime.UtcNow;
((IBaseEntity)entry.Entity).LastDateModifiedBy = _userName;
});
// Added
var added = ChangeTracker.Entries().Where(v => v.State == EntityState.Added && typeof(IBaseEntity).IsAssignableFrom(v.Entity.GetType())).ToList();
added.ForEach(entry =>
{
((IBaseEntity)entry.Entity).DateCreated = DateTime.UtcNow;
((IBaseEntity)entry.Entity).DateCreatedBy = _userName;
((IBaseEntity)entry.Entity).LastDateModified = DateTime.UtcNow;
((IBaseEntity)entry.Entity).LastDateModifiedBy = _userName;
});
}
// ...
}
在Startup中添加HttpContextAccessor:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
现在,每次保存实现IBaseEntity的对象时,字段都会自动更新.
请注意,我没有在这里注入UserManager.如果用户包含名称声明,则可以使用该声明.这将保存对数据库的调用.
作为改进,您可以编写一个新服务,负责解析用户名并将其注入.
内容总结
以上是互联网集市为您收集整理的c# – 如何将计算值添加到此TryUpdateModelAsync <>中全部内容,希望文章能够帮你解决c# – 如何将计算值添加到此TryUpdateModelAsync <>中所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。