• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
夕月かかりて、にほひ淡し
はるかぜ、くさはら、穏やかな微笑み。長い髪、まっしろなキミ、ゆらす―― 白と黒のハーモニー。
博客园    首页    新随笔    联系   管理    订阅  订阅
使用DbContext時,不獲取實體更新數據的注意點

其實真的是個很無聊的問題…但一不小心就會中套,留條記錄備忘好了。

我就是想單純的增加某個實體的點擊量,也不在意並發,如果還要獲取實體再update真是毫無意義。

於是:

public IShoppingService IncreaseGoodsHits(Guid id)
{
    long hits = _ctx.Commodities.Where(c => c.Id == id && !c.IsOffShelves).Select(c => c.Hits).SingleOrDefault();
    var goods = new Commodity { Id = id, Hits = ++hits };
    try
    {
        _ctx.Commodities.Attach(goods);
        _ctx.Entry(goods).Property(c => c.Hits).IsModified = true;
        _entities.SaveChanges();
    }
    catch
    {
    }
    
    return this;
}

好吧我悲劇了。原因很簡單,這個表有一個RowVersion字段,而且他的Concurrency Mode是Fixed(廢話),所以想要更新就必須獲取RowVersion字段並且將EF的Validation關閉。這是因為有timestamp的情況下EF將使用pk和timestamp作為update的where子句,如果不獲取那麼會拋出DbConcurrencyException異常,而不關閉Validation則會在Save時自動驗證實體,我只寫了一個Hits,必然會拋出DbEntityValidationException異常…這樣的話是無論如何也沒法update了。

於是修改如下: 

public IShoppingService IncreaseGoodsHits(Guid id)
{
    try
    {
        var hits = _ctx.Commodities.Where(c => c.Id == id && !c.IsOffShelves).Select(c => new { c.Hits, c.RowVersion }).Single();
        var goods = new Commodity { Id = id, Hits = hits.Hits + 1, RowVersion = hits.RowVersion };
        _ctx.Configuration.ValidateOnSaveEnabled = false;
        _ctx.Commodities.Attach(goods);
        _ctx.Entry(goods).Property(c => c.Hits).IsModified = true;
        _entities.SaveChanges();
    }
    catch
    {
    }
    finally
    {
        _ctx.Configuration.ValidateOnSaveEnabled = true;
    }
    
    return this;
}

好了,看看生成的SQL: 

exec sp_executesql N'SELECT TOP (2) 
1 AS [C1], 
[Extent1].[Hits] AS [Hits], 
[Extent1].[RowVersion] AS [RowVersion]
FROM [dbo].[Commodities] AS [Extent1]
WHERE ([Extent1].[Id] = @p__linq__0) AND ([Extent1].[IsOffShelves] <> cast(1 as bit))
',N'@p__linq__0 uniqueidentifier',@p__linq__0='B07D0508-1142-4A89-821A-49DFA189C88A'

exec sp_executesql N'update [dbo].[Commodities]
set [Hits] = @0
where (([Id] = @1) and ([RowVersion] = @2))
select [RowVersion]
from [dbo].[Commodities]
where @@ROWCOUNT > 0 and [Id] = @1
',N'@0 bigint,@1 uniqueidentifier,@2 binary(8)',@0=34,@1='B07D0508-1142-4A89-821A-49DFA189C88A',@2=0x000000000001733D

似乎沒什麼問題了,就先這樣吧。 

 

Rayless,
and pathless,
and the icy earth,
Swung blind
and blackening
in the moonless air.
posted on 2013-01-17 05:59  夕月  阅读(246)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3