Как мне легко хранить записи в базе данных, связанные друг с другом?

StackOverflow https://stackoverflow.com/questions/1409206

  •  05-07-2019
  •  | 
  •  

Вопрос

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

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

Пример того, как этот процесс должен работать с точки зрения строк в базе данных:

Страховой идентификатор, Тип страхования, Основной Страховой идентификатор, Статус

1, Автострахование, нулевое, Активное

2, Защита от ветра, 1, Активна

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

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

1, Автострахование, нулевое, Неактивный

2, Защита от ветра, 1, Активна

3, Автострахование, нулевое, Активный

Когда я обрабатываю вторую политику, я получаю следующее:

1, Автострахование, нулевое, Неактивное

2, Страхование от ветра, 1, Неактивный

3, Автострахование, нулевое, Активное

4, Страхование от ветра, 1, Активный // должно быть 3, а не 1

Вы заметите, что когда я создаю страховку нового окна, поскольку мы копируем старую строку, в итоге мы получаем страховку основного идентификатора, указывающую на неактивную строку.

Чтобы обойти это, я должен отслеживать основной страховой идентификатор предыдущего полиса, который был обработан, что привело к следующему коду:

int masterInsuranceId = -1;
foreach(Policy policy in policyList)
{
    //copy the old policy so the new policy has 
    //the same details as the old one
    Policy newPolicy = policyManager.Copy(policy);

    //if the new policy is not the master insurance store 
    //the master its new master insuance
    if(newPolicy.MasterInsuranceId.HasValue)
    {
       newPolicy.MasterInsuranceId = masterInsuranceId; 
    }

    //save the details of the new policy
    policyManager.SavePolicy(newPolicy);

    //record the master id so we can update the master id 
    //reference on the next policy
    if(newPolicy.MasterInsuranceId == null)
    {
        masterInsuranceId = newPolicy.Id;
    }
    else
    {
        masterInsuranceId = -1;
    }

    //inactivate the current policy
    policy.Status = Inactive;
    policyManager.UpdatePolicy(policy);

}

Кто-нибудь знает, как это можно упростить?Каков наилучший способ гарантировать, что две записи будут оставаться связанными друг с другом, даже когда история изменений записывается для каждого изменения, внесенного в запись?

Это было полезно?

Решение 3

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

Потратив некоторое время в выходные на эту проблему, я придумал решение, которое, на мой взгляд, немного упрощает код, хотя он все еще далек от совершенства.

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

Policy Convert(Policy policy, Policy masterPolicy)
{
    Policy newPolicy = policyManager.Copy(policy);

    //link the policy to it's master policy
    if(masterPolicy != null)
    {
        newPolicy.MasterPolicyId = masterPolicy.Id;
    }

    SavePolicy(newPolicy);

    //inactivate the current policy
    policy.Status = Inactive;
    policyManager.UpdatePolicy(policy);

    return newPolicy;
}

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

Policy newPolicy = null;
foreach(Policy policy in policyList)
{
    Policy masterPolicy = policy.MasterPolicyId.HasValue ? newPolicy : null;
    newPolicy = Convert(policy, masterPolicy);   

}

Когда все сказано и сделано, кода становится не намного меньше, но я считаю, что он гораздо более понятен и позволяет преобразовывать отдельные политики.

Другие советы

Какую схему базы данных вы используете?Обычно именно здесь должна храниться взаимосвязь, и я думаю, что это должно быть реализовано на уровне обработки данных, а не кода.

Вот очень упрощенная рекомендация

страхование (< insurance_id >, название, описание)

страховой элемент(< item_id >, < insurance_id >, название, описание)

страховый_элемент_детали(< item_id >, < policy_id >, когда_ изменен)

insurance__полис имеет отношение "1 ко многим" к insurance_item.Страховой __элемент имеет отношение "один ко многим" с insurance_item_details.Каждая строка в сведениях о страховании __товара__ представляет собой изменение в полисе.

Таким образом, SQL-сервер может быстро получить последние два элемента

SELECT FROM insurance_item_details, insurance_item, insurance where
             insurance_item_details.item_id = insurance_item.item_id
             AND insurance_item.insurance_id = insurance.insurance_id
             ORDER BY when_changed
             LIMIT 1

Или вы даже можете восстановить историю событий.

(SQL не был опробован)

Итак, идея в том, что вы не дублируете insurance_item - у вас есть другая таблица для хранения элементов, которые будут изменены, и прикрепите к ней временную метку, представляющую это изменение как связь.

Я не гуру SQL (к сожалению), но все, что вам нужно сделать, это вставить в таблицу insurance_item_details вместо создания копий.Судя по тому, как это выглядит, я думаю, что создание копий, подобных вашему исходному примеру, нарушает 2NF.

ЕСЛИ бы у вас был плохой дизайн кода и вам нужно было внести изменения, провели бы вы рефакторинг?Тогда почему бы вам не рассмотреть возможность рефакторинга плохого дизайна базы данных?Это то, что более эффективно обрабатывается в базе данных благодаря хорошему дизайну.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top