我想在仅附加数据存储区中重新实现一些现有的SQLAlchemy模型; append-only意味着该对象仅使用INSERT语句更新,而不是使用UPDATE或DELETE语句.
UPDATE和DELETE语句将替换为增加版本的另一个INSERT.将有一个is_deleted标志而不是DELETE,is_deleted=True将创建一个新版本:
id | version | is_deleted | name | description ...
---- --------- ------------ ----------- ---------------
1 | 1 | F | Fo | Text text text.
1 | 2 | F | Foo | Text text text.
2 | 1 | F | Bar | null
1 | 3 | T | Foo | Text text text.
Run Code Online (Sandbox Code Playgroud)
另外,
我知道如何解决大多数这些问题,但我正在努力处理SQLAlchemy中的事件挂钩,它将处理需要在更新和删除时完成的某些事情.
SQLAlchemy文档已经有一些版本控制的基本示例.该版本行例子来接近我想要的东西,但他们不处理(1)删除和(2)外键关系.
(1)删除.我知道有一个session.deleted字段,我将以类似于如何session.dirty在versioned_rows.py …
我可以在ManyToMany引用表上添加SoftDelete行为,这将添加deleted_at列.不幸的是,将列设置为非NULL值,不会过滤掉关系.这就是我所希望的.
有没有人知道一个解决方法而没有实际引用参考表?
我正试图在Laravel中实现软删除.
这是我的关系
Tournament ( hasMany ) CategoryTournament (hasOne) CategorySettings
Tournament ( hasMany ) CategoryTournament (belongsToMany) CategoryTournamentUser
Run Code Online (Sandbox Code Playgroud)
所以,我用这个答案帮了我很多忙
现在,当我SoftDelete锦标赛时,所有与之相关的CategoryTournaments也会被删除.
但后来,我尝试递归地应用它,所以我在CategoryTournament模型中编写了相同的代码:
static::deleting(function($categoryTournament) {
$categoryTournament->settings()->delete();
$categoryTournament->users()->delete();
});
Run Code Online (Sandbox Code Playgroud)
但是这段代码从未运行过.我检查了我有设置和用户删除,但没有一个被软删除...
我错过了什么???它应该工作!
编辑:
现在,我正在尝试软删除用户,它只是一个级别:
User (HasMany) Tournament ( hasMany ) CategoryTournament (hasOne) CategorySettings
Run Code Online (Sandbox Code Playgroud)
所以现在,当我软删除用户时,它会删除他的锦标赛,但它不再删除他的CategoryTournaments,所以这不是配置错误.
为Doctrine 2安装和使用SoftDeleteable行为扩展非常简单.问题通常是尝试为某些代码部分禁用它并再次启用.您可能希望这样做:
那么如何禁用它呢?
我正在使用一个数据库,设计人员决定用IsHistorical位列标记每个表.没有考虑正确的建模,我无法改变架构.
在开发与导航属性交互的CRUD屏幕时,这会引起一些摩擦.我不能简单地拿一个产品然后编辑它的EntityCollection我必须手动编写IsHistorical检查到处都是它让我疯了.
添加也很可怕,因为到目前为止我已经编写了所有手动检查以查看添加是否只是软删除,因此我可以切换IsHistoric而不是添加重复的实体.
我考虑过的三个选项是:
修改t4模板以包括IsHistorical检查和同步.
拦截ObjectContext中的删除和添加,切换IsHistorical列,然后同步对象状态.
订阅AssociationChanged事件并在那里切换IsHistorical列.
有没有人有这方面的经验或者可以推荐最无痛的方法?
注意:是的,我知道,这是不好的建模.我已经阅读了有关软删除的相同文章.它很臭,我必须处理这个要求,但我这样做.我只想要最轻松的处理软删除的方法,而无需为我的数据库中的每个导航属性编写相同的代码.
注意#2 LukeLed的答案在技术上是正确的,虽然迫使你陷入一个非常糟糕的穷人ORM,无图形,模式.问题在于,现在我需要从图中删除所有"已删除"的对象,然后在每个对象上调用Delete方法.那不是真的会省去那么多手工仪式编码.现在我没有编写手动IsHistoric检查,而是收集已删除的对象并循环遍历它们.
我们应该使用标志进行软删除还是单独的连接表?哪个更有效率?数据库是SQL Server.
背景资料
前一阵子,我们有一位DB顾问进来查看我们的数据库架构.当我们软删除记录时,我们将更新相应表上的IsDeleted标志.有人建议,不要使用标志,而是将已删除的记录存储在单独的表中,并使用连接,因为这样会更好.我已经把这个建议付诸实践,但至少在表面上,额外的表和连接看起来比使用标志更昂贵.
初步测试
我已经设置了这个测试.
两个表,Example和DeletedExample.我在IsDeleted列上添加了一个非聚集索引.
我做了三次测试,加载了一百万条记录,其中包含以下已删除/未删除的比率:
结果 - 50/50

结果 - 10/90

结果 - 1/99

数据库脚本,供参考,示例,DeletedExample和Example.IsDeleted的索引
CREATE TABLE [dbo].[Example](
[ID] [int] NOT NULL,
[Column1] [nvarchar](50) NULL,
[IsDeleted] [bit] NOT NULL,
CONSTRAINT [PK_Example] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Example] ADD CONSTRAINT [DF_Example_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]
GO
CREATE TABLE …Run Code Online (Sandbox Code Playgroud) 我正在使用带有StofDoctrineExtensionsBundle的DoctrineExtensions来获取软删除行为.
它在我的应用程序的前端非常有效.
在后端我需要"硬"删除实体的选项.
我在管理员控制器中禁用了过滤器(我使用SonataAdmin):
$filters = $this->getModelManager()->getEntityManager($this->getClass())->getFilters();
if (array_key_exists('softdeleteable', $filters->getEnabledFilters())) {
$filters->disable('softdeleteable');
}
Run Code Online (Sandbox Code Playgroud)
这工作(软删除的实体显示在列表中),但当我尝试删除它时,实体再次被软删除.我怎么能强行"硬"删除?
我使用以下教程实现了数据库软删除(一个将条目标记为已删除的布尔标志):http://www.codeguru.com/csharp/csharp/soft-deleting-entities-cleanly-using-entity-framework- 6- interceptors.html
在我看来,这是一个非常好的实现,因为一旦设置了软删除,只需添加[SoftDelete("IsDeleted")]注释就可以应用于模型.问题到目前为止它无法正常工作.
来源似乎是可靠的,他们甚至发布了他们的解决方案的一个例子:https://github.com/rakeshbabuparuchuri/EFExpensionPoints
在将软删除应用到我的项目中时,如果我做错了什么,你能看看我的代码吗?
这是模型:
[SoftDelete("IsDeleted")]
public class BC_Instance
{
public int ID { get; set; }
public bool IsDeleted { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
ApplicationDbContext.cs:
namespace bcplatform2.Models
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
// Add a DbSet for each one of your Entities
//public DbSet<VirtualGuest> VirtualGuests { get; set; }
public DbSet<BC_Instance> BiocloudInstances { get; set; }
static ApplicationDbContext()
{ …Run Code Online (Sandbox Code Playgroud) 我在 Symfony 框架中使用表单集合软删除项目有问题
我想添加和删除与 Symfony 表单集合相关的项目,如果我从集合中删除项目,此项目必须从关系记录中软删除
用下图你可以想象关系
这是我在 Symfony 表单中的表单集合
Main form
+
|
ProductType+
| |
| |
| PackagesType+
| |
| |
| PackageProductsType
|
|
+
Run Code Online (Sandbox Code Playgroud)
基于表单集合的Symfony示例在前端使用JS添加和删除包产品
我的问题是,当我在实体的注释中package_product通过激活orphanRemoval=true完全删除时,每件事都运行良好,但记录完全删除,我想根据我的建议软删除记录,但是当我在Package实体中更改以下功能时
Main form
+
|
ProductType+
| |
| |
| PackagesType+
| |
| |
| PackageProductsType
|
|
+
Run Code Online (Sandbox Code Playgroud)
始终在顶部功能中,我获取最后一条记录packageProducts,当我删除此行$packageProduct->setPackage(null);以禁用记录中的丢失数据并将其替换$packageProduct->setDeletedAt(new \Datetime());为设置已删除项目时,在保存的记录中删除记录从数据库中删除并添加了一条新记录,其中填充了最后一条记录数据并删除了约会时间。
例如:
PackageProduct 删除第一项之前的记录:
+----+------------+------------+--------+-----------+
| ID | Product_id | package_id …Run Code Online (Sandbox Code Playgroud) 建议阅读
我怎么在这里结束
我非常相信,在制作软件时,任何事情都要事先做好,以便以后最大限度地减少工作量.因此,我试图确保在接近我的数据库架构和维护时,它可以保持关系完整性,而不是过时或过于复杂.
在查看典型的删除方法CASCADE时,这会让人有些不寒而栗.哎呀,对我目前的情况来说有点过头了.我想保持关系图的完整性,但我不想删除每个图只是因为链的一部分是无关紧要的.因此,我选择采用软删除的方式,以确保数据完整性保留,同时记录可以从相关性中删除.我通过在数据库中的每个叹息表中添加"DateDeleted"字段来完成此操作.
转折点
然而,这显然开始增加太多的复杂性并且值得付出努力.我将逻辑放在不应该去的地方,并且不想在整个应用程序中使这些不良做法永久化.简而言之,我将回滚此实现.
在查找天气或不是人们喜欢软删除时,似乎有很多支持它.事实上,链接的"相似"帖子顶部是"我总是软删除"的最高投票回答.此外,那里和SO周围的大多数答案包括某种"isDeleted"或"isActive"类型的方法.
新的实施理念
链接的"好文章"涵盖了我实际遇到的一些问题.它还提出了一种替代软删除的方法,我从最佳实践的角度出发.建议使用"存档数据库",我在查看软删除时实际考虑过.我决定反对它的原因是因为我之前提到的有关CASCADE删除的观点.我很谨慎从数据库中删除整个图表,因为链的一部分被删除了.但是,这个图表至少可以从档案中保留,所以我不确定它真的那么糟糕.
十字路口
那么,我应该继续添加逻辑,逻辑,逻辑......逻辑吗?或者,我是否应该考虑创建归档数据库,其中大多数逻辑只是位于一个非常复杂的图形管理类中来存储/恢复关系对象图?后者似乎对我来说是最好的做法.
soft-delete ×10
doctrine-orm ×2
php ×2
symfony ×2
asp.net ×1
c# ×1
database ×1
doctrine ×1
indexing ×1
laravel ×1
many-to-many ×1
mysql ×1
postgresql ×1
python ×1
sonata-admin ×1
sql ×1
sqlalchemy ×1
symfony-2.1 ×1
symfony4 ×1