Какова лучшая стратегия для зеркалирования удаленной БД в Core Data? - PullRequest
0 голосов
/ 22 апреля 2011

Допустим, у меня есть две таблицы в БД: расходы и учетная запись. Расходы - это данные, которые меня интересуют, и эта таблица имеет внешний ключ для учетной записи. Эта БД является удаленной, доступ к ней осуществляется с помощью команд Restful-esque, и я хочу отобразить только те данные, которые мне нужны для моего приложения, в хранилище данных Core Data на iPhone. Реальная БД, с которой я работаю, намного больше, чем этот пример. ~ 30 таблиц и таблица расходов ~ 7 ФК. Я работаю в тесном контакте с человеком, занимающимся разработкой API, поэтому при необходимости могу изменить способ выполнения своих запросов или возвращаемых данных.

Какова наилучшая стратегия для загрузки этих данных в Core Data?

Моей первой мыслью было, чтобы запрос расходов вернул идентификаторы для FK.

<expense>
    <date>1/1/2011</date>
    <cost>1.50</cost>
    <account_id>123</account_id>
</expense>

Это прекрасно работает, если у меня уже есть учетная запись с идентификатором '123' в моем хранилище данных. Если я этого не сделаю, тогда мне придется делать дополнительные веб-запросы каждый раз, когда я сталкиваюсь с идентификатором, которого у меня нет ... который будет невероятно медленным. Я могу обойти это, делая запросы в определенном порядке, то есть запрашивая все новые учетные записи, прежде чем запрашивать расходы, так что я знаю, что все строки FK существуют. Я чувствую, что это станет слишком громоздким, когда БД начнет достигать умеренной сложности.

Моя вторая мысль состояла в том, чтобы данные, возвращаемые из запроса, следовали за FK и возвращали данные из FK.

<expense>
    <date>1/1/2011</date>
    <cost>1.50</cost>
    <account>
        <id>123</id>
        <name>Bob's Big Boy</name>
        <address>1234 Main Street</address>
    </account>
</expense>

Это выглядит лучше и гарантирует, что у меня будут все необходимые данные, когда они мне понадобятся. Если у меня еще нет учетной записи «123», я могу создать новый объект учетной записи из этого XML. Однако меня беспокоит этот метод: по мере усложнения базы данных эти XML-файлы могут стать чрезмерно большими. Таблица расходов имеет ~ 7 внешних ключей, каждая из этих таблиц имеет несколько FK. Такое ощущение, что простой запрос только одного Расхода может в конечном итоге вернуть огромный кусок данных.

Как другие люди решили эту проблему?

1 Ответ

1 голос
/ 22 апреля 2011

Я предполагаю, что в любой момент времени вы хотите кэшировать только часть базы данных сервера в локальном приложении и что кэшированные данные могут со временем меняться.

Вы, вероятно, хотите использовать объекты-заглушки для представления связанных объектов, которые вы еще не загрузили. Вы должны настроить объекты следующим образом:

Expense{
  date:Date
  cost:Number 
  account<<-->AccountStub.expenses
}

AccountStub{
  id:Number
  expenses<-->>Expenses.account
}

Account:AccountStub{
  name:String
  address:String
}

У сущности AccountStub есть минимальная минимальная информация, необходимая для идентификации учетной записи в БД сервера на основе информации, предоставленной из таблицы расходов. Он служит в качестве заполнителя в графе объектов для полноценного объекта Account (вы можете рассматривать его как тип ошибки, если хотите.)

Поскольку расходы связаны с AccountStub, а Account наследуется от AccountStub, вы можете при необходимости заменить Account на AccountStub (и наоборот).

Вам потребуется предоставить собственный подкласс для AccountStub и Account, чтобы AccountStub мог инициировать загрузку данных учетной записи и создание объекта Account, когда эти данные действительно требуются. Затем новый объект Account должен быть заменен на AccountStub во всех его отношениях (для этого может потребоваться много кода).

Для использования вы должны сначала получить данные для объекта Расходы и создать этот объект. Вы попытаетесь получить AccountStub с идентификатором, предоставленным из данных таблицы расходов. Установите выборку для включения подстатей. Если объект AccountStub или Account существует с этим идентификатором, вы добавите объект Expense в отношение. Если нет, вы создаете объект AccountStub с этим идентификатором и добавляете его в отношение. Теперь у вас есть базовый граф объектов, показывающий связь объекта Expense с объектом AccountStub. Чтобы получить доступ к данным учетной записи Расхода, вы должны сначала проверить, является ли связанная учетная запись тупой или полной учетной записью. Если это заглушка, то перед загрузкой необходимо загрузить полные данные учетной записи.

Преимущество этой системы в том, что вы можете поддерживать довольно сложный граф объектов, не имея фактически всех данных локально. Например. Вы можете поддерживать несколько отношений и ходить эти отношения. Например, вы можете расширить свою модель следующим образом:

AccountStub{
  id:Number
  expenses<-->>Expenses.account
  owner<<--AccountOwnerStub.accounts
}

AccountOwnerStub{
    id:Number
    accounts<-->>AccountStub.owner
}

AccountOwner{
    name:String
    address:String
    bill:Number
}

Если вы хотите найти имя владельца учетной записи объекта Expense, вы просто проведете отношения по заглушкам с помощью account.owner.name сам объект Account останется просто заглушкой.

Если вам нужно сохранить комнату локально, вы можете вернуть объект обратно в заглушку, не ставя под угрозу график.

Это потребует некоторой работы, и вам придется следить за заглушками, но это позволит вам зеркалировать сложную внешнюю БД без необходимости хранить все данные под рукой.

...