请教EF中Timestamp列的使用

我想实现对数据的并发修改控制,先说一下我的实现方法,请大家看一下问题出在那里。

先在实体类中添加Timestamp属性,对应数据库中该列设置为timestamp类型,属性设置如下:
[Timestamp]
public byte[] Version { get; set; }

用户在修改记录里时,我先用一个 @Html.HiddenFor(m => m.Version)将Version列的值缓存起来。
然后在保存方法如下:
public OperationResult Modify(Models.Projects.Projects t)
{
Models.Projects.Projects m_Projects = GetModel(t.ItemCode);

m_Projects.ItemCode = t.ItemCode;
m_Projects.ItemName = t.ItemName;
……
m_Projects.Version = t.Version;

try
{
int i = db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
throw ex;
}
}
我将页面初始化的实体类传到Modify方法中,在Modify方法中再取一遍实体数据,再将需要修改的值替换掉新的实体类,同时将新的实体类的Version字段的值替换成参数中的Version字段(也就是页面上缓存的Version值。)

然后我模拟数据的修改,先打开修改页面(Version值已经缓存),然后在数据库中修改掉数据,再在页面上提交修改,但一直不触发异常,请问大家这其中有什么问题?
...全文
613 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
1.数据库已经对行版本进行了自动管理了,你所要做的就是在程序中进行比较 2.指定某些列不需要修改,通过属性的封装来实现比较好,简单地你可以声明为protected set,复杂的你自己实现get和set结构
  • 打赏
  • 举报
回复
引用 6 楼 dongxinxi 的回复:
Version 为Timestamp列。但发现m_Projects.Version好像并不接受我的赋值 在SQL中本来就是这样的,上面我也说了,对用户而言它是只读的 在.Net中正是因为加了Timestamp特性,EF在处理里也完全遵循数据库中的标准来处理
那请问要如何同时实现我5楼说的两个功能呢? 1,实现版本控制 2,保存数据时,指定某些列的数据不需要修改(比如录入时间,录入人等,这些字段只要添加后,就不需要再修改了)
  • 打赏
  • 举报
回复
引用 6 楼 dongxinxi 的回复:
Version 为Timestamp列。但发现m_Projects.Version好像并不接受我的赋值 在SQL中本来就是这样的,上面我也说了,对用户而言它是只读的 在.Net中正是因为加了Timestamp特性,EF在处理里也完全遵循数据库中的标准来处理
但编译却是可以通过的,太坑了……
  • 打赏
  • 举报
回复
Version 为Timestamp列。但发现m_Projects.Version好像并不接受我的赋值 在SQL中本来就是这样的,上面我也说了,对用户而言它是只读的 在.Net中正是因为加了Timestamp特性,EF在处理里也完全遵循数据库中的标准来处理
  • 打赏
  • 举报
回复
引用 3 楼 dongxinxi 的回复:
你的查询怎么写的,执行前把SQL打印出来,与数据库实际执行的对比看看 你试下先不带version条件,利用主键查询出来,然后取version跟你自己纪录的去比较
测试出来问题了。 之前因为在修改数据时需要排除一些列不要修改,有朋友说在修改时需要再从数据库中读取一次实体类,然后修改需要修改的字段,没有修改的字段自然就不会到生成的sql中了,最后代码如下: public OperationResult Modify(Models.Projects.Projects t) { Models.Projects.Projects m_Projects = GetModel(t.ItemCode); m_Projects.ItemCode = t.ItemCode; m_Projects.ItemName = t.ItemName; m_Projects.PItemCode = t.PItemCode; m_Projects.CID = t.CID; m_Projects.Responsible = t.Responsible; m_Projects.PlanBeginDate = t.PlanBeginDate; m_Projects.PlanEndDate = t.PlanEndDate; m_Projects.ActualBeginDate = t.ActualBeginDate; m_Projects.ActualEndDate = t.ActualEndDate; m_Projects.Progress = t.Progress; m_Projects.Remark = t.Remark; m_Projects.Version = t.Version; int i = Db.SaveChanges(); return (i == 1) ? t.ToOperationResultSuccess() : t.ToOperationResultNoChanged(); } 以上Version 为Timestamp列。但发现m_Projects.Version好像并不接受我的赋值,它总是最新的值。 然后直接 public OperationResult Modify(Models.Projects.Projects t) { Db.Entry(t).State = EntityState.Modified; int i = Db.SaveChanges(); return (i == 1) ? t.ToOperationResultSuccess() : t.ToOperationResultNoChanged(); } 就没有问题
winner2050 2014-08-05
  • 打赏
  • 举报
回复
行版本的字段是全自动维护的
  • 打赏
  • 举报
回复
你的查询怎么写的,执行前把SQL打印出来,与数据库实际执行的对比看看 你试下先不带version条件,利用主键查询出来,然后取version跟你自己纪录的去比较
  • 打赏
  • 举报
回复
引用 1 楼 dongxinxi 的回复:
Timestamp的值是由数据库维护的,不得人为进行修改(不能出现在insert或者update语句的操作列中) 说白了,对于你而言他就是一个只读的标记列 你应该在更新数据savechanges后,重新读取Version的值,并更新到你的缓存中
我跟踪了最终执行的sql语句,并没有对Timestamp列进行修改,在读取数据的时候,增加了where version='值' 的条件。但这个where version='值'的值一直都是数据库中最新的,并不是我最初存在页面中的那个值。
  • 打赏
  • 举报
回复
Timestamp的值是由数据库维护的,不得人为进行修改(不能出现在insert或者update语句的操作列中) 说白了,对于你而言他就是一个只读的标记列 你应该在更新数据savechanges后,重新读取Version的值,并更新到你的缓存中

62,047

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧