实现要在数据库中删除的对象列表

时间:2012-10-08 19:15:41

标签: c# linq list ado.net generic-list

我有一个包含少量标签的表单,并且在每个标签中都有一个网格控件。当用户选择要删除的行时,我想将其从网格中删除,如果数据库中存在该对象,则将其删除,但不是永久性的 - 仅当用户单击保存表单时。

现在,如果db中不存在object,则将其从列表中删除,如果db中存在对象,则从db中删除它并从列表中删除它。但是,如果用户单击“取消”按钮,则表示不希望从数据库中删除行。

我脑子里有两种可能的解决方案:1) - 从列表中删除对象,如果db中存在对象,则将其添加到要删除的对象列表中2) - 实现另一个列表,getter将仅返回具有状态的对象!= ToBeDeleted(表现?)

注意:我没有使用ORM工具,使用我自己的基于ado.net的数据访问框架。

1 个答案:

答案 0 :(得分:0)

我认为你所描述的案例只是要求交易。

如果你使用合理的数据库引擎(例如:没有SqlServerCE,例如:),ADO.Net可以轻松处理它们。)

例如参见TransactionScope类。您在与数据库交互之前构造此类对象,并且更改将是"提交"当且仅当您调用Complete()时。如果您不管它或者Dispose()它,交易将被取消,并且数据库上的所有更改将被"回滚",因此,还原。

因此,在您的情况下,您可以在表格的ctor或onLoaded()中完成交易,并在"保存"和任何其他窗口关闭的Dispose()中完成()

虽然这是处理小型系统(尤其是单用户系统)的正常方式,但要小心:如果您的系统必须处理许多可靠的用户,您可能无法以这种方式使用它。事务阻止行和表,直到它完成或取消,因此"其他用户"可能会看到很大的延误..

那么,您需要支持多少用户以及他们尝试编辑相同内容的频率?

- 编辑:(10位用户)

对于那么多用户,您将希望避免长时间运行的事务。在表单加载时打开事务将是不可接受的,并且将锁定许多用户,直到当前一个用户关闭窗口。但是,使用Save()中的事务来推送一批中的所有更改都可以。

当然,如果你可以完全取消交易 - 这太棒了!但是,如果您还需要保持数据完整性,这是非常困难的事情。为了消除事务的需要,几乎总是您必须重新设计数据库端的数据结构,以及获取和使用数据结构的方式。数据。如果你想重新设计两者,那么我真的建议首先尝试重新设计它以使用一些现有的数据访问框架,因为即使是基本的.Net ADO也具有非常好的功能,可以在线编辑符合SqlClient标准的数据库数据库..

因此,假设您不想重写/重新考虑大部分代码,您只需要缓冲数据,并且延迟所有对数据库的实际操作。

你可能想要在一个简单的" form:当您显示表单时,而不是将表单直接绑定到数据库驱动的数据源 - 将所有必需的数据下载到某些BindingList<>,DataTables等 - 您喜欢的任何容器。并将您的表单绑定到他们身上。可能你已经设置了类似的东西。但是,重要的是,所有这些datacontainers必须离线或至少 readonly + delayloaded

接下来,您必须拦截用户在UI上执行的所有操作。当然你已经完成了它,因为我假设应用程序正常工作:)由于你的表单绑定到那些离线缓存项目,你的应用程序应该对该缓存数据执行操作,而不要触摸数据库一点都不但还有更多:在缓存数据上执行它们时,您应该记录哪个表发生了什么。

然后,当最终用户停止播放并按CANCEL :)时 - 您只需删除所有内容并关闭表单。数据库没有改变。

在保存时 - 您打开一个新的事务,然后遍历更改列表并在数据库上有效地重放您的记录器更改,然后提交事务。

请注意两件事:数据库可能在用户缓存数据的时间和按下Save的时间内发生了变化。您必须检测到并中止或解决冲突。您应该在执行记录的更改期间或之前执行该事务。您可以通过简单地将在线数据与离线缓存数据(未更改的原始值,而不是用户修改的数据)进行比较来检测它,或者您可以使用其他一些机制,例如OptimisticLocking,只需比较版本标签行。

如果您不喜欢录制重播,您可以实施一个" DIFF" ing实用程序,它可以获取修改后的脱机数据,并以通用方式将其与当前在线表进行比较。这有点难度,但有一个额外的好处:有了这样的实用程序,你最初可以加倍缓存数据:一个副本用于离线引用(只是存储而且从未被用户触摸)和一个副本用于离线编辑(所有那些绑定到形式)。现在,在保存时,您打开事务并将参考数据与在线数据库区分开来。如果有任何差异 - 您刚刚检测到碰撞。解决/合并/失败/等。如果没有差异,则将修改后的数据与在线数据区分开来,并将发现的所有差异应用于数据库并提交事务。

这两种方法都有其优点和缺点:除了执行困难之外,如果您敢于复制太大的表,还存在缓存的内存问题,延迟问题等等。

但是 - 一旦解决了,它会很好用。

当你完成时,你可以吹嘘你刚刚实施了一个较小的sis' DataSet + DataTable。我不是在开玩笑,我也不是在嘲笑你。我只是想告诉你为什么每个人都在告诉你重新审视你的DAO层并尝试理解和使用平台设计人员/开发人员已经为你完成的努力工作:)

无论如何,我已经说过,如果你重新考虑你的数据结构,你可以完全避免冲突和交易。例如:你为什么要删除行?我知道SQL中有一个漂亮的DELETE语句,但是,你真的需要删除那一行吗?你不能只添加一些“bool isDeleted”'当用户从网格中删除行时 - 只需将该行设置为True并使应用程序过滤掉任何isDeleted = true行而不显示它们?并不将它们包含在视图和聚合中?奖励:sys / db管理员现在有一个神奇的工具:取消删除..

让我们更进一步:你需要更新行吗?也许你可以只附上一些来自(这个日期)该行应该有新价格的信息?当然,结构必须大大改变:实体没有属性,但有时间戳属性更改的日志(或者行必须具有版本号并且是重复的......),查询必须仅针对最新的versiosn数据等。优点:数据库现在仅附加。如果需要的话,交易是超短的。缺点:SELECT查询很复杂,可能很慢,尤其是在连接多个表时..

Pro / Con:你的数据库实际上开始看起来非常元而不是数据库...

Con:这对于"升级"这是一项非常艰巨的任务。这种数据库结构的现有应用。从头开始编写新应用程序并从odl系统导入数据可能会快几倍。

现在,总结一下:

  • 我不推荐任何描述的方式。
  • 首先,我建议您从DevExpress或其他方面采用一些ORM框架,如NHibernate,EntityFramework,XPO。他们中的任何一个都会为你节省很多时间。我在这里列出的三个甚至内置了OptimisticLocking碰撞检测。为什么在存在这样的工具时使用SQL自编框架?
  • 如果没有,那么接下来我建议使用框架中的现有工具。你使用SqlClient,whydontya使用DataSet和DataTables?它们与SqlClient一起提供,它们有许多内置的有用机制,否则您将花费​​数周时间自行实现和测试。学习使用DataSet及其碰撞检测及其合并算法,并使用它们。你将在实验和学习上花费一些时间,但是你将节省大量的时间来重新发明轮子。
  • 如果你真的想手动完成,请先从数据缓存和记录重放开始。很容易理解,在目前使用普通SQL查询的任何地方都很容易介绍,并且会很快向您介绍各种缓存同步和版本检查问题,您很快就会详细了解为什么所有这些都是奇怪的实施了上述框架中的机制,它们的工作方式以及它们的优缺点。
  • 以及关于双重缓存的差异方法..编写记录报告会更具吸引力,但请:只有在您非常清楚如何检测/解决/合并冲突时才使用它。在尝试之前至少实施了一种记录重播方法..

..当然,你可以使用持久的交易。愚蠢易于介绍,他们只是激怒"用户..好吧,甚至当> 90%的用户经常碰撞并锁定锁时,甚至使系统无法使用,嘿..不,这是一个笑话。不要使用持久的交易。它们适用于1-4个用户或非常稀疏的数据库..

相关问题