DBAccess - 是否可以在单个事务中创建和链接实体?

时间:2015-07-14 18:48:07

标签: dbaccess

我遇到了交易和链接实体的问题。我有这样的代码(不是真正的代码,只是为了得到这个想法):

Card * card;
for (card in otherCards) {
    // do something
}

使用此方案编码没有事务,它工作正常。但是一旦我尝试在事务中执行它,我最终会在Session和Config中没有链接用户对象(事务内部的查询永远不会找到以前提交的对象)。据我从文档中了解,提交不是事务提交,而是插入或更新。

有没有办法让这样的操作(创建和链接多个实体)在使用DBAccess的事务中工作?

谢谢,

MIC

1 个答案:

答案 0 :(得分:0)

对不起延迟,我以为我对此作出了回应,但显然我心烦意乱。

我已经完全复制了你的问题,我想解释你为什么看到自己的问题。

如果我们根据您的反馈采取以下示例:

[DBTransaction transaction:^{

            Department *dept = [Department new];
            dept.name = @"test dept";
            [dept commit];

            dept = [[[Department query] where:@"name = 'test dept'"] fetch].firstObject;

            Person *person = [Person new];
            person.Name = @"test";
            person.department = dept;
            [person commit];

            person = [[[Person query] whereWithFormat:@"department = %@", dept.Id] fetch].firstObject;

        } withRollback:^{

        }];

原因是,您拥有的方案是因为DBAccess根据对提交删除的任何调用记录所有对象更改和说明。

这些都包含在一个事务中,因此当块中的代码运行时,我们按照它们被调用的顺序构建一个指令列表,然后一旦块运行,我们执行事务并寻找错误。

这意味着,当您在块内时,查询将不会返回结果,因为记录尚未在数据库中。

因此,DBAccess事务在概念上与SQL事务不相似。我想解释一下,为什么会出现这种情况,主要是处理数据库命令与ORM对象之间的区别。

我们的原始实现正如您所期望的那样,事务只是启动一个新事务,然后按顺序执行SQL并提交它。

问题出现了,因为您可以在 entityWillDelete 更新插入方法中的交易或交易中进行交易。或者甚至只是取消从事件模型生成的事件,SQL对此一无所知。

因此,在事务中锁定该表的数据编写器对象只会导致锁定的线程。因此,我们重新编写了事务系统,以记录要进行的更改列表,并提交它们,包括可能使用触发器或事件创建的任何子项或相关更改。

这就是我们现在所处位置的原因。其中,我是第一个承认的,并不理想。

那么,我们从哪里开始呢?

那取决于使用交易背后的原因。如果是出于性能原因,那么你可以使用DBContext,它的工作方式与普通的SQL事务非常相似,但也有一个缺点,就是不跟踪任何可能无意中被调用的其他代码对任何对象所做的所有更改。块内的代码。

下面是一个正确使用嵌入对象的上下文示例,但您查询的原始问题仍然存在问题。

DBContext* c = [DBContext new];

        Department *dept = [Department new];
        dept.name = @"test dept";
        [c addEntityToContext:dept];

        Person *person = [Person new];
        person.Name = @"test";
        person.department = dept;
        [c addEntityToContext:person];

        [c commit];

但如果您的目的是避免孤立记录或数据完整性问题,那么上下文并不理想,因为没有回滚子句。

最初DBAccess由于一个非常简单的原因没有任何事务支持,除了数据库损坏或空间不足之外,无法意外或故意产生错误,这些错误会阻止对象被提交到数据库。对持久性功能的所有对象分配都进行了测试,如果开发人员试图存储ORM中不支持的对象,则会在代理上引发错误,但这将是一个编码错误,在所有版本的应用程序,将在测试中找到。

这是一个我欣赏的重要声明,但没有任何约束,灵活的类型存储系统,如果需要,它将在一个数字列中存储一个字符串,线程安全和使用WAL来克服SQLite的遗产这些并发问题的问题。

对象也可以在树中持久化,因此如果你有一个person类并且有一个相关对象被定义为属性,那么person on person将在一个操作中提交任何子对象,并且级联向下。

并非所有人都对这种实施感到满意,因此我们将交易作为一种让人们感觉更舒服的方法实现。

那么现在呢?

嗯,你的例子中肯定有一个有效的错误,因为对象comital和赋值的级联被打破了。作为object.Id被拉出并作为参数添加到SQL语句中,但该对象尚未在该点分配PK值。所以我们将解决这个问题,以存储实际的DBObject本身,在执行特定语句时,它将被分配一个PK值,从而解决了这个问题。

作为一种现在应该可行的解决方法,使用基于NSString *的Id列将生成一个在持久性之前可用的GUID。

如果您希望向我们发送电子邮件,我们会及时通知您,或者您确实希望向我们提供反馈或实施建议,我们将非常感激。

由于 阿德里安