Как установить для внешнего ключа значение null, если ключи сущности имеют тип bigint (ulong)?

В моей модели я использую bigint (ulong) в качестве типа для ключей сущности. Я хочу, чтобы база данных обеспечивала ссылочную целостность, поэтому я установил для persistenceEnforce значение true. Столбцы для внешних ключей могут принимать значения NULL. При ссылочной целостности объект может быть удален только в том случае, если ни один внешний ключ не ссылается на объект, поэтому перед удалением объекта я должен сначала установить каждый внешний ключ для этого связанного объекта равным нулю. Однако я не знаю, как очистить внешний ключ.

Вот моя модель:

<cf:entity name="Order" cfom:bindingList="false">
  <cf:property name="Id" typeName="ulong" key="true" persistenceIdentity="true" cfps:hint="CLUSTERED" />
  <cf:property name="Invoice" typeName="Invoice" persistenceEnforce="true" />
</cf:entity>

<cf:entity name="Invoice" cfom:bindingList="false">
  <cf:property name="Id" typeName="ulong" key="true" persistenceIdentity="true" cfps:hint="CLUSTERED" />    
  <cf:property name="Name" typeName="string" />
</cf:entity>

Вот мой код:

Invoice invoice = new Invoice();
invoice.Save();

Order order = new Order();
order.Invoice = invoice;
order.Save();

// We must clear the reference to the invoice before deleting the invoice,
// because the database enforces referential integrity.
order.InvoiceId = 0;
order.Save();

invoice.Delete();

Приведенный выше код вызывает следующее исключение при сохранении заказа во второй раз: Оператор UPDATE конфликтует с ограничением FOREIGN KEY \"FK_Ord_Ore_Inv_Inv\".

Это связано с тем, что код, созданный CodeFluent, вставляет значение 0 вместо нуля в столбец «Order_Invoice_Id». Следующая строка в методе Order.BaseSave кажется неверной: persistence.AddParameter("@Order_Invoice_Id", this.InvoiceId, ((ulong)(0ul)));

Я пробовал использовать настройки persistenceDefaultValue="null" и usePersistenceDefaultValue="true" в свойствах Invoice, но это не решило проблему.


person Willem    schedule 13.07.2016    source источник


Ответы (1)


Примечание. Свойство типа UInt64 (без знака) преобразуется в столбец типа bigint< /a> (подписано). Так что будьте осторожны с преобразованиями... FYI CodeFluent Entities использует CodeFluent.Runtime.Utilities.ConvertUtilities для преобразования значений.

Перегрузка AddParameter(string name, ulong value, ulong defaultValue) не использует значение по умолчанию, поэтому она не преобразует значение по умолчанию в NULL. В качестве обходного пути вы можете создать PersistenceHook, который изменяет значение параметра в соответствии с ожидаемым поведением:

public class CustomPersistenceHook : BasePersistenceHook
{
    public override void AfterAddParameter(string name, object value, IDbDataParameter parameter)
    {
        if (value is ulong && name == "@Order_Invoice_Id")
        {
            var defaultValue = (ulong)ContextData["defaultValue"];
            if (defaultValue == (ulong)value)
            {
                parameter.Value = DBNull.Value;
            }
        }

        base.AfterAddParameter(name, value, parameter);
    }
}

Затем вам нужно зарегистрировать хук сохранения:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="Sample" type="CodeFluent.Runtime.CodeFluentConfigurationSectionHandler, CodeFluent.Runtime" />
  </configSections>

  <Sample persistenceHookTypeName="Sample.CustomPersistenceHook, Sample" />
</configuration>
person meziantou    schedule 13.07.2016