Атомарные транзакции в хранилищах значения ключа

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

Предположим, у нас есть параметр типа в универсальном методе, и нам нужно сделать с ним некоторую операцию. Мы не хотим мгновенно, потому что мы не знаем конструкторов.

Например:

Repository GetRepository<T>()
{
  //need to call T.IsQueryable, but can't!!!
  //need to call T.RowCount
  //need to call T.DoSomeStaticMath(int param)
}

...
var r = GetRepository<Customer>()

К сожалению, я могу придумать только «некрасивые» альтернативы:

  • Использовать отражение [1118 Уродлив и бьет идею интерфейсов и полиморфизма.

  • Создать полностью отдельный фабричный класс

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

  • Создавать и вызывать нужный интерфейсный метод

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

Пример:

public class Customer 
{
  //create new customer
  public Customer(Transaction t) { ... }

  //open existing customer
  public Customer(Transaction t, int id) { ... }

  void SomeOtherMethod() 
  { 
    //do work...
  }
}

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

public class Customer: IDoSomeStaticMath
{
  //create new customer
  public Customer(Transaction t) { ... }

  //open existing customer
  public Customer(Transaction t, int id) { ... }

  //dummy instance
  public Customer() { IsDummy = true; }

  int DoSomeStaticMath(int a) { }

  void SomeOtherMethod() 
  { 
    if(!IsDummy) 
    {
      //do work...
    }
  }
}

Это, очевидно, некрасиво, а также излишне усложняет код для всех других методов. Очевидно, что это тоже не элегантное решение!

17
задан ChrisInEdmonton 7 July 2009 в 15:44
поделиться

1 ответ

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

Если вам нужно обновить два баланса (то есть перевод с одного аккаунта на другой), тогда вам нужно использовать отдельный документ транзакции (фактически другую таблицу, где строки являются транзакциями), в котором хранится сумма и два счета (входящий и исходящий). Кстати, это обычная бухгалтерская практика. Поскольку CouchDB вычисляет представления только по мере необходимости, на самом деле все еще очень эффективно вычислять текущую сумму в учетной записи на основе транзакций, которые перечисляют эту учетную запись. В CouchDB вы должны использовать функцию карты, которая выдавала номер учетной записи в качестве ключа и сумму транзакции (положительная для входящей, отрицательная для исходящей). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов.

Поскольку CouchDB вычисляет представления только по мере необходимости, на самом деле все еще очень эффективно вычислять текущую сумму в учетной записи на основе транзакций, которые перечисляют эту учетную запись. В CouchDB вы должны использовать функцию карты, которая выдавала номер учетной записи в качестве ключа и сумму транзакции (положительная для входящей, отрицательная для исходящей). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов.

Поскольку CouchDB вычисляет представления только по мере необходимости, на самом деле все еще очень эффективно вычислять текущую сумму в учетной записи на основе транзакций, которые перечисляют эту учетную запись. В CouchDB вы должны использовать функцию карты, которая выдавала номер учетной записи в качестве ключа и сумму транзакции (положительная для входящей, отрицательная для исходящей). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов.

отрицательный для исходящих). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов.

отрицательный для исходящих). Ваша функция сокращения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов.

11
ответ дан 30 November 2019 в 13:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: