Skip to content

Instantly share code, notes, and snippets.

@jvanhoesen
Created June 2, 2021 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jvanhoesen/16b0c6caf9d37d73cd0fd55072550135 to your computer and use it in GitHub Desktop.
Save jvanhoesen/16b0c6caf9d37d73cd0fd55072550135 to your computer and use it in GitHub Desktop.
Selects DACs from the database including Extension fields
public static IEnumerable<TNode> SelectRecords(params PXDataField[] restricts)
{
//Retrieves table structure for specified TNode
TableHeader tableStructure = PXDatabase.GetTableStructure(typeof(TNode).Name);
//Should be null if there's no Table, IE if you're using a Synthetic DAC
if (tableStructure != null)
{
List<PXDataField> parameters = new List<PXDataField>();
IEnumerable<PXDataRecord> selectDel = null;
List<string> allFields = StaticInfo._FieldsMap.Keys.ToList();
List<string> validFields = new List<string>();
//We couldn't find a way yet to check the Attributes without using Reflection.
if (!typeof(TNode).IsDefined(typeof(PXTableAttribute), false))
{
validFields.AddRange(StaticInfo._FieldsMap.Keys.ToList().Intersect(tableStructure.Columns.Select(x => x.Name), StringComparer.InvariantCultureIgnoreCase));
foreach (string field in validFields)
{
parameters.Add(new PXDataFieldMapping(new Column(field), field));
}
parameters.AddRange(restricts);
selectDel = PXDatabase.SelectMulti<TNode>(parameters.ToArray());
}
else
{
List<Tuple<string, string>> fieldVsTable = new List<Tuple<string, string>>();
fieldVsTable.AddRange(tableStructure.Columns.Select(x => new Tuple<string, string>(typeof(TNode).Name, x.Name)));
TableHeader baseStructure;
TableHeader prevStructure = tableStructure;
List<YaqlJoin> joins = new List<YaqlJoin>();
YaqlCondition condition;
foreach (Type baseType in typeof(TNode).BaseTypes())
{
condition = null;
baseStructure = PXDatabase.GetTableStructure(baseType.Name);
fieldVsTable.AddRange(baseStructure.Columns.Select(x => new Tuple<string, string>(baseStructure.Name, x.Name)).Where(y => !fieldVsTable.Exists(z => string.Equals(z.Item2, y.Item2, StringComparison.InvariantCultureIgnoreCase))));
//The 1st Index in this list should always be the Primary Key
//The 1st field in the 1st Index is the CompanyID
//I prefer to join on x.CompanyID = y.CompanyID
//For some reason Acumatica's code joins on x.CompanyID = 2 instead of adding it as a where clause
foreach (TableIndexOnColumn key in baseStructure.Indices[0].Columns)
{
//Extension Tables need to have the same Keys with the same names, so this should be fine
if (condition == null)
{
condition = Yaql.column(key.Name, baseStructure.Name).eq(Yaql.column(key.Name, prevStructure.Name));
}
else
{
condition = condition.and(Yaql.column(key.Name, baseStructure.Name).eq(Yaql.column(key.Name, prevStructure.Name)));
}
}
//I don't think the Extension Table can exist without the base table.
//Left Join just in case
joins.Add(Yaql.join(baseStructure.Name, condition, YaqlJoinType.LEFT));
if (!baseType.IsDefined(typeof(PXTableAttribute), false))
{
break;
}
prevStructure = baseStructure;
}
validFields.AddRange(fieldVsTable.Select(x => x.Item2));
parameters.AddRange(fieldVsTable.Select(x => new PXDataFieldMapping(new Column(x.Item2, x.Item1), x.Item2)));
parameters.AddRange(restricts);
selectDel = PXDatabase.SelectMulti<TNode>(joins, parameters.ToArray());
}
TNode row;
PXCacheExtension[] extensions;
//For each data record selected retrieve associated extensions
foreach (PXDataRecord pxDataRecord in selectDel)
{
if (pxDataRecord != null)
{
row = Activator.CreateInstance<TNode>();
extensions = GetExtensions(row);
for (int i = 0; i < validFields.Count; ++i)
{
StaticInfo._SetValueByOrdinal(row, StaticInfo._FieldsMap[validFields[i]], pxDataRecord.GetValue(i), extensions);
}
yield return row;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment