我应该在删除之前检查一行是不是存在吗?
Posted
技术标签:
【中文标题】我应该在删除之前检查一行是不是存在吗?【英文标题】:Should I check if a row exists before deletion?我应该在删除之前检查一行是否存在吗? 【发布时间】:2010-12-15 22:22:50 【问题描述】:我使用 Mssql 作为数据库,使用 EF4 作为 ORM/DAL。 我的问题是关于以下代码:
public static void DeleteBuilding(int buildingId, int countryId)
PlayerBuilding playerBuilding = new PlayerBuilding()
CountryID = countryId,
BuildingID = buildingId
;
Entities.PlayerBuildings.Attach(playerBuilding);
Entities.PlayerBuildings.DeleteObject(playerBuilding);
Entities.SaveChanges();
如果行存在,这很好用,如果不存在我得到一个异常(存储更新、插入或删除语句影响了意外的行数 (0)。实体可能有自加载实体后被修改或删除。刷新 ObjectStateManager 条目。) 我是否应该像这样来回访问数据库以检查该行是否存在:
public static void DeleteBuilding(int buildingId, int countryId)
PlayerBuilding playerBuilding = (from p in Entities.PlayerBuildings
where p.BuildingID == buildingId && p.CountryID == countryId
select p).FirstOrDefault();
if (playerBuilding != null)
Entities.PlayerBuildings.DeleteObject(playerBuilding);
Entities.SaveChanges();
我认为额外的往返是不必要的,因为没有 EF,使用纯 SQL,我可以使用单个 DELETE 命令简单地删除该行。
什么是更好的做法?
【问题讨论】:
【参考方案1】:该错误是 Entity Framework 的乐观并发的副作用。
基本上,其他人可能在您检索记录之间删除了该记录。或者,您可能在该代码之前对实体进行了某些操作。
尝试在隔离环境中运行它(例如单元测试),看看您是否仍然遇到问题。
是的,您可以放心地再次获得记录,或者您可以使用 ObjectContext.Refresh:
public static void DeleteBuilding(int buildingId, int countryId)
PlayerBuilding playerBuilding = new PlayerBuilding()
CountryID = countryId,
BuildingID = buildingId
;
try
Entities.PlayerBuildings.Attach(playerBuilding);
Entities.PlayerBuildings.DeleteObject(playerBuilding);
Entities.SaveChanges();
catch (OptimisticConcurrencyException)
Entities.Refresh(RefreshMode.ClientWins, playerBuilding);
Entities.SaveChanges();
附带说明 - 可能是因为您的方法是静态?你如何实例化你的上下文?我希望你没有使用单例。 :(
有一篇关于 EF 乐观并发here 的优秀文章,其中更详细地解释了为什么会出现该错误,以及可以采取哪些步骤来解决它。
【讨论】:
感谢 RPM 的评论,但这不是一个乐观的并发问题。我正在使用本地开发人员计算机,尝试了非静态方法,这也不是问题。使用此方法实例化上下文:dotnetslackers.com/articles/ado_net/…。使用正常的方式来实例化上下文而不改变任何东西。 看看这篇文章——那篇文章中的错误和你的完全一样。您是否尝试在单元测试(隔离)中运行上述代码?另外-您提供的那篇文章中的哪种方式实例化了上下文? (那篇文章中有多种方法) 我使用了 UnitOfWorkScope 方法,但这不是问题所在。即使我使用旧方式(MyContext context = new MyContext()) 实例化上下文,也会继续显示相同的错误。我认为它与并发无关,显示错误是因为我正在尝试删除上下文中不存在的对象。 好的。您是否在我的回答中尝试过上面的“刷新”方法?附带说明一下,当您知道对象不存在时,您是否应该首先调用此方法?以上是关于我应该在删除之前检查一行是不是存在吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何在合并数据集之前检查行是不是存在(SQL Server)