如何使用Realm编写更好的数据访问层 [英] How to write a better data access layer with Realm

查看:107
本文介绍了如何使用Realm编写更好的数据访问层的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一些小项目中一直使用Realm,我非常喜欢它。我希望继续在更大的项目中使用它,我正在寻找更好的结构我的数据访问层。

I've been using Realm in a few small projects and I quite like it. I'm hoping to move on to using it in bigger projects and I'm looking for better structure my data access layer.

我遇到了类似的问题并试图建立我在那里找到的信息。在那里讨论的方法是DAO模式,所以我给了它一个镜头。

I came across this similar question and tried to build up on the information I found there. The approach discussed there is the DAO pattern so I gave a shot at that.

这是我的模型类。

class Chat: Object {
    dynamic var id: String = ""
    dynamic var createdAt: Date = Date()
    dynamic var creatorId: String = ""
    dynamic var title: String?
    let chatMessages = List<ChatMessage>()

    override static func primaryKey() -> String? {
        return "id"
    }

    convenience init(fromJSON json: JSON) {
        self.init()
        // ...
    }
}

然后我创建了一个 ChatDAOProtocol 保存所有便利帮助方法。

Then I created a ChatDAOProtocol to hold all the convenience helper methods.

protocol ChatDAOProtocol {
    func addMessage(_ message: ChatMessage)
    func getChatThumbnail() -> UIImage
    func getParticipants(includingMe: Bool) -> [Participant]?
    static func getChat(fromId id: String) -> Chat?
    static func getChat(fromCreatorId id: String) -> Chat?
}

最后我创建了另一个名为 ChatHelper 实现了所有这些协议方法。

Lastly I created another class called ChatHelper that implemented all those protocol methods.

class ChatHelper: ChatDAOProtocol {
    func addMessage(_ message: ChatMessage) {

    }

    func getChatThumbnail() -> UIImage {
        return UIImage()
    }

    func getParticipants(includingMe: Bool) -> [Participant]? {
        return nil
    }

    static func getChat(fromId id: String) -> Chat? {
        return nil
    }

    static func getChat(fromCreatorId id: String) -> Chat? {
        return nil
    }

}

这似乎比在VC和东西上遍布所有数据库相关代码更好。但我仍然有一些疑问。

This already seems better than sprinkling all the database related code all over the VCs and stuff. But I still have some doubts.

例如,如果我需要让所有参与者都聊天,现在我必须在<$ c上调用该方法$ c> ChatHelper class。如果我想简单地获得聊天标题,我会调用 Chat 对象本身的 title 属性。看起来不像一个非常统一的界面。我是否应该在帮助程序中包含所有属性的getter和setter。因此,永远不会直接调用 Chat 对象(除了可能创建实例)。

For example, say if I need to get all the participants of a chat, now I have to call the method on the ChatHelper class. And if I want to get simply the chat title, I call the title property of the Chat object itself. Doesn't seem like a very unified interface. Should I include getters and setters for all the properties in the helper as well. So the Chat object is never directly called (except for maybe creating an instance).

我应该使 Chat 对象本身符合 ChatDAOProtocol 协议吗?所以所有便利方法以及属性都可以直接从 Chat 对象直接访问?

Should I make the Chat object itself conform to the ChatDAOProtocol protocol? So all the convenience methods as well as the properties are directly accessible from the Chat object straight up?

或者是还有比这两种更好的方法吗?

Or is there a better way than both of these?

推荐答案

这是一个相当棘手的问题,因为它真的取决于你想要多少从与Realm的直接交互中抽象出来,以及你想要多少与Realm的性能妥协。

This is pretty tricky sort of question since it really depends on how much you want to abstract away from directly interacting with Realm, and how much you want to compromise with Realm's performance.

就我个人而言,我认为如果你抽象掉查询并写逻辑,但仍然直接从Realm模型对象读取。如果你移动到另一个基于对象的数据库(像核心数据),那么当你重构父类时,这些对象属于其他东西(例如, RLMObject NSManagedObject ),你的业务逻辑从这些对象中读取的方式不会改变。

Personally, I think it is fine if you are abstracting away query and write logic, but still directly reading from Realm model objects. If you moved to another object-based database (Like Core Data), then while you would refactor the parent class these objects belonged to something else (eg, RLMObject to NSManagedObject), the way your business logic read from these objects wouldn't change.

你必须要小心一件事虽然以一种非常低效地利用Realm的方式抽象逻辑。

One thing you definitely need to be careful though is abstracting the logic in such a way that will utilize Realm very inefficiently.

我可以看到的主要示例是在你的 getParticipants 方法中,你将返回一个标准的Swift数组。将领域结果对象转换为这样会导致分页内存中的每个对象(与请求时的延迟加载相反),因此您将失去很多Realm性能优势。但由于 Results 对象的行为与标准数组类似,如果直接返回,则无需更改业务逻辑。

The main example of this I can see is in your getParticipants method, you're returning a standard Swift array. Converting a Realm Results object to such would result in paging every object in memory (as opposed to lazy-loading on request), so you would lose a lot of Realm performance benefits. But since Results objects behave like standard arrays, you wouldn't need to change your business logic if you directly returned one.

另一个考虑因素:如果你正在更新一批对象上的单个属性,那么最好确保在单个写入事务中更新所有对象,而不是在内部每次打开写入事务的助手类调用辅助方法的时间。

Another consideration: if you're updating a single property on a batch of objects, you would be much better off ensuring all of the objects are updated in a single write transaction, instead of the helper class internally opening a write transaction each time the helper method is called.

这篇关于如何使用Realm编写更好的数据访问层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆