I'm faced to a behavior in caches that I don't understand.
I created a custom DAC, say MyDAC.
In a graph, I create an instance of this DAC like this :
PXCache myCache = myGraph.Caches[typeOf(MyDAC)];
MyDAC myDacInstance = myCache.Insert();
So far, so good : at this moment, myCache contains one record in its inserted collection (I can check it via debug mode in Visual Studio).
Then I modify the properties of the "myDacInstance" object :
myDacInstance.xxx = 10;
Finally, I update the cache with the following instruction :
myCache.Update(myDacInstance);
And then the magic happens: instead of having a single record in myCache, I have two ! Each of course has exactly the same characteristics (even for key properties), so on saving, the system throws an error indicating that there are duplicates. It looks like the Update method fails to recognize that a record having the same key values already exists in cache and create a new record instead of using it.
I checked for key declarations in MyDac and everything seems to be ok. If someone has an idea, it would be appreciated.
Below the code of the DAC I’m using :
using PX.Data;
using PX.Data.BQL;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.Objects.CM;
using PX.Objects.CS;
using PX.Objects.TX;
using System;
namespace Test.DAC
{
[Serializable()]
[PXCacheName(PX.Objects.AP.Messages.APTax)]
public class EAPTax : TaxDetail, IBqlTable
{
public static bool IsActive() => PXAccess.FeatureInstalled<FeaturesSetExt.cegEInvoicing>();
#region Keys
public class PK : PrimaryKeyOf<EAPTax>.By<tranType, refNbr, lineNbr, taxID>
{
public static EAPTax Find(PXGraph graph, String tranType, String refNbr, Int32? lineNbr, String taxID) => FindBy(graph, tranType, refNbr, lineNbr, taxID);
}
public static class FK
{
public class Document : EAPRegister.PK.ForeignKeyOf<EAPTax>.By<tranType, refNbr> { }
public class DocumentLine : EAPTran.PK.ForeignKeyOf<EAPTax>.By<tranType, refNbr, lineNbr> { }
public class CurrencyInfo : PX.Objects.CM.CurrencyInfo.PK.ForeignKeyOf<EAPTax>.By<curyInfoID> { }
public class Tax : PX.Objects.TX.Tax.PK.ForeignKeyOf<EAPTax>.By<taxID> { }
}
#endregion
#region TranType
public abstract class tranType : BqlString.Field<tranType> { }
[PXDBString(3, IsKey = true, IsFixed = true)]
[PXDBDefault(typeof(EAPRegister.docType))]
[PXUIField(DisplayName = "Tran. Type", Visibility = PXUIVisibility.Visible, Visible = false)]
public virtual String TranType { get; set; }
#endregion
#region RefNbr
public abstract class refNbr : BqlString.Field<refNbr> { }
[PXDBString(15, IsUnicode = true, IsKey = true)]
[PXDBDefault(typeof(EAPRegister.refNbr))]
[PXUIField(DisplayName = "Reference Nbr.", Visibility = PXUIVisibility.Visible, Visible = false)]
public virtual String RefNbr { get; set; }
#endregion
#region LineNbr
public abstract class lineNbr : BqlInt.Field<lineNbr> { }
[PXDBInt(IsKey = true)]
[PXDefault()]
[PXUIField(DisplayName = "Line Nbr.", Visibility = PXUIVisibility.Visible, Visible = false)]
[PXParent(typeof(Select<EAPRegister, Where<EAPRegister.docType, Equal<Current<tranType>>, And<EAPRegister.refNbr, Equal<Current<refNbr>>>>>))]
[PXParent(typeof(Select<EAPTran, Where<EAPTran.tranType, Equal<Current<tranType>>, And<EAPTran.refNbr, Equal<Current<refNbr>>, And<EAPTran.lineNbr, Equal<Current<lineNbr>>>>>>))]
public virtual Int32? LineNbr { get; set; }
#endregion
#region TaxID
public abstract class taxID : BqlString.Field<taxID> { }
[PXDBString(Tax.taxID.Length, IsUnicode = true, IsKey = true)]
[PXDefault()]
[PXUIField(DisplayName = "Tax ID")]
[PXSelector(typeof(Tax.taxID), DescriptionField = typeof(Tax.descr))]
public override String TaxID { get; set; }
#endregion
#region TaxRate
public abstract class taxRate : BqlDecimal.Field<taxRate> { }
#endregion
#region CuryInfoID
public abstract class curyInfoID : BqlLong.Field<curyInfoID> { }
[PXDBLong()]
[CurrencyInfo(typeof(EAPRegister.curyInfoID))]
public override Int64? CuryInfoID { get; set; }
#endregion
#region CuryOrigTaxableAmt
public abstract class curyOrigTaxableAmt : BqlDecimal.Field<curyOrigTaxableAmt> { }
[PXDBCurrency(typeof(curyInfoID), typeof(origTaxableAmt))]
[PXDefault(TypeCode.Decimal, "0.0")]
public virtual Decimal? CuryOrigTaxableAmt { get; set; }
#endregion
#region OrigTaxableAmt
public abstract class origTaxableAmt : BqlDecimal.Field<origTaxableAmt> { }
[PXDBDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0")]
public virtual Decimal? OrigTaxableAmt { get; set; }
#endregion
#region CuryTaxableAmt
public abstract class curyTaxableAmt : BqlDecimal.Field<curyTaxableAmt> { }
[PXDBCurrency(typeof(curyInfoID), typeof(taxableAmt))]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Taxable Amount", Visibility = PXUIVisibility.Visible)]
public virtual Decimal? CuryTaxableAmt { get; set; }
#endregion
#region TaxableAmt
public abstract class taxableAmt : BqlDecimal.Field<taxableAmt> { }
[PXDBDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Taxable Amount", Visibility = PXUIVisibility.Visible)]
public virtual Decimal? TaxableAmt { get; set; }
#endregion
#region CuryTaxAmt
public abstract class curyTaxAmt : BqlDecimal.Field<curyTaxAmt> { }
[PXDBCurrency(typeof(curyInfoID), typeof(taxAmt))]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Tax Amount", Visibility = PXUIVisibility.Visible)]
public virtual Decimal? CuryTaxAmt { get; set; }
#endregion
#region TaxAmt
public abstract class taxAmt : BqlDecimal.Field<taxAmt> { }
[PXDBDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Tax Amount", Visibility = PXUIVisibility.Visible)]
public virtual Decimal? TaxAmt { get; set; }
#endregion
#region CuryExpenseAmt
public abstract class curyExpenseAmt : BqlDecimal.Field<curyExpenseAmt> { }
[PXDBCurrency(typeof(curyInfoID), typeof(expenseAmt))]
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Expense Amount", Visibility = PXUIVisibility.Visible)]
public override Decimal? CuryExpenseAmt{ get; set; }
#endregion
#region ExpenseAmt
public abstract class expenseAmt : BqlDecimal.Field<expenseAmt> { }
#endregion
#region CuryTaxableDiscountAmt
public abstract class curyTaxableDiscountAmt : BqlDecimal.Field<curyTaxableDiscountAmt> { }
[PXDBCurrency(typeof(curyInfoID), typeof(taxableDiscountAmt))]
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
public virtual decimal? CuryTaxableDiscountAmt{get; set;}
#endregion
#region TaxableDiscountAmt
public abstract class taxableDiscountAmt : BqlDecimal.Field<taxableDiscountAmt> { }
[PXDBDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
public virtual decimal? TaxableDiscountAmt { get; set; }
#endregion
#region CuryTaxDiscountAmt
public abstract class curyTaxDiscountAmt : BqlDecimal.Field<curyTaxDiscountAmt> { }
[PXCurrency(typeof(curyInfoID), typeof(taxDiscountAmt))]
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
public virtual decimal? CuryTaxDiscountAmt { get; set; }
#endregion
#region TaxDiscountAmt
public abstract class taxDiscountAmt : BqlDecimal.Field<taxDiscountAmt> { }
[PXDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
public virtual decimal? TaxDiscountAmt { get; set; }
#endregion
#region CuryRetainedTaxableAmt
public abstract class curyRetainedTaxableAmt : BqlDecimal.Field<curyRetainedTaxableAmt> { }
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
[PXDBCurrency(typeof(curyInfoID), typeof(retainedTaxableAmt))]
[PXUIField(DisplayName = "Retained Taxable Amount", Visibility = PXUIVisibility.Visible, FieldClass = nameof(FeaturesSet.Retainage))]
public virtual decimal? CuryRetainedTaxableAmt
{
get;
set;
}
#endregion
#region RetainedTaxableAmt
public abstract class retainedTaxableAmt : BqlDecimal.Field<retainedTaxableAmt> { }
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
[PXDBDecimal(4)]
[PXUIField(DisplayName = "Retained Taxable Amount", Visibility = PXUIVisibility.Visible)]
public virtual decimal? RetainedTaxableAmt
{
get;
set;
}
#endregion
#region CuryRetainedTaxAmt
public abstract class curyRetainedTaxAmt : BqlDecimal.Field<curyRetainedTaxAmt> { }
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
[PXDBCurrency(typeof(curyInfoID), typeof(retainedTaxAmt))]
[PXUIField(DisplayName = "Retained Tax", Visibility = PXUIVisibility.Visible, FieldClass = nameof(FeaturesSet.Retainage))]
public virtual decimal? CuryRetainedTaxAmt
{
get;
set;
}
#endregion
#region RetainedTaxAmt
public abstract class retainedTaxAmt : BqlDecimal.Field<retainedTaxAmt> { }
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
[PXDBDecimal(4)]
[PXUIField(DisplayName = "Retained Tax", Visibility = PXUIVisibility.Visible)]
public virtual decimal? RetainedTaxAmt
{
get;
set;
}
#endregion
#region tstamp
public abstract class Tstamp : BqlByteArray.Field<Tstamp> { }
[PXDBTimestamp()]
public virtual Byte[] tstamp { get; set; }
#endregion
}
}