Axapta: "The record has never been selected" error after Group By clause - group-by

I'm new in Ax 2009.
I would like to update the field of a record in table A after joining with another table B on which I want to apply Group by on its ID.
I tried to run the following code but it throw me an error "Cannot edit a record in tableA. The record has never been selected":
where select forupdate tableA group by tabAid, Dimension[5]
join tableB group by tabBid, Dimension[5]
where tableA.tabAid == tableB.tabBid && tableB.Dimension[5] != "" && tableA.Dimension[5]
{
if(tableA.Dimension[5] != lines.Dimension[5])
{
ttsbegin;
tableA.Dimension[5] = tableB.Dimension[5];
tableA.update()
ttscommit;
}
}
I think it should be caused by the usage of Group By clause on tableA but if i remove it, on the if check, the tableA.Dimension[5] is empty.
Please someone help me.
Thank you.

Yes, the problems are the Group by clauses. Try something like this.
ttsbegin;
while select forupdate tableA where tableA.Dimension[5] != ""
join tableB where tableB.tabBid == tableA.tabAid && tableB.Dimension[5] != ""
{
if(tableA.Dimension[5] != tableB.Dimension[5])
{
tableA.Dimension[5] = tableB.Dimension[5];
tableA.update()
}
}
ttscommit;
*I made the code without compiler, maybe it needs some adjustment.

Related

How to extract the Rationale and Problem applied to a Requirement artifact in Enterprise Architect through API

I have a few requirements defined in the Requirement Diagram as shown in the below picture. I want to fetch the Rationale and Problem that are attached to the Requirement through API.
The DB has no relationship between the Requirement and Note in the t_object table. Do I have to look up in some other table? Please suggest.
EA.Elements(t_object) are connected with each other using EA.Connector (t_connector)
So in order to get from your requirement to your note, you can do something like this
foreach (EA.Connector connector in myRequirement.Connectors)
{
EA.Element otherElement;
if (connector.ClientID != myRequirement.ElementID)
{
otherElement = myRepository.GetElementByID(connector.ClientID)
}
else
{
otherElement = myRepository.GetElementByID(connector.ClientID)
}
if (otherElement.Type == "Note")
{
return otherElement;
}
}
In a query you can something like this
select note.*
from t_object o
inner join t_connector c on o.Object_ID in (c.Start_Object_ID, c.End_Object_ID)
inner join t_object note on note.Object_ID in (c.Start_Object_ID, c.End_Object_ID)
and note.Object_Type = 'Note'
where o.ea_guid = '<myRequirementGUID>'

Select in Data dictionary

i want get all table names where created person is not "-AOS-" (Dynamics AX). In this code i get only who created first line in table:
for (tablecounter=1; tablecounter<=dict.tableCnt(); tablecounter++)
{
tableId = dict.tableCnt2Id(tablecounter);
common = new DictTable(tableId).makeRecord();
select common where common.createdBy !="";
if(common)
{
info(strFmt('%1---%2',common.createdBy,dict.tableName(common.TableId)));
}
}
You can try with scan over SysModelElement and SysModelElementData tables.
SysModelElement me;
SysModelElementData med;
while select firstOnly10 me
where me.ElementType == UtilElementType::Table
exists join med
where med.ModelElement == me.RecId
&& med.createdBy != '-AOS-'
{
info(me.Name);
}
You could also use the project filter (probably not as fast as a direct SQL query, but depending on your requirements more actionable).

Account Trigger update all contacts - Too many SOQL queries: 101

I have a trigger that runs after updating any account and it actually just updates a field (Relationship_category_r__c) in all the related contacts after few conditions.
Condition1: If we update the account type to "Member"
Condition2: If the contact doesn't have "Member" already in the (Relationship_category_r__c) field
ACTION: Update the contact Relationship_Category_r__c field to "Member - staff"
Condition2: If we update the account type to "Member - past"
ACTION: Update all the contacts Relationship_Category_r__c field to "Member - past"
The trigger works absolutely find when the account has less than 25 to 50 contacts but it generates an error when we have an account more than 55 or so contacts
ERROR: Apex trigger UpdateAllContacts caused an unexpected exception, contact your administrator: UpdateAllContacts: System.LimitException: Too many SOQL queries: 101
======================================= TRIGGER ==============================
trigger UpdateAllContacts on Account (after update) {
for ( Account acc : Trigger.New ) {
List<Contact> listCon = [Select id, Relationship_Category_r__c from Contact where AccountId =: acc.id];
for ( Contact con : listCon ) {
if ( acc.Type=='Member' ) {
if ( con.Relationship_Category_r__c != 'Member' ) {
con.Relationship_Category_r__c = 'Member - staff';
}
} else if ( acc.Type=='Member - past ' ) {
con.Relationship_Category_r__c = 'Member - past';
}
}
try {
update listCon;
}
catch (DmlException e) {}
}
}
Any help will be greatly appreciated
Thanks
Couple of things that jump out at me here:
First and foremost is the main cause of your error: a SOQL query within a loop. You need to bulkify your trigger to perform a single query, rather than querying once for each Account record in your update batch.
You have a DML operation (update listCon;) within that same loop, which will exacerbate the problem if you happen to have any SOQL queries in your Contact triggers. This update should also be bulkified, so that you are making as few inserts/updates as possible (in this case you can limit it to a single update call).
You are updating all Contact records queried regardless of whether or not they've been updated by your code. This can lead to unnecessarily long processing times, and can easily be prevented by keeping track of which records should be updated in a second list.
This may be by design, but you're suppressing any errors in your update call without even attempting to deal with them. There are many different ways to go about this depending on your implementation so I won't delve into that, but in most circumstances you would probably want to at least be aware that your update to those records was failing so you can correct the issue.
After making a few corrections to your code we are left with the following which uses a single SOQL query, single DML statement, and won't update any Contact records that haven't been modified by the trigger:
trigger UpdateAllContacts on Account (after update) {
List<Contact> updateCons = new List<Contact>();
for ( Contact con : [select Id, AccountId, Relationship_Category_r__c from Contact where AccountId in :Trigger.NewMap.keySet()] ) {
Account parentAcc = Trigger.NewMap.get(con.AccountId);
if ( parentAcc.Type == 'Member' ) {
if ( con.Relationship_Category_r__c != 'Member' ) {
con.Relationship_Category_r__c = 'Member - staff';
updateCons.add(con);
}
} else if ( parentAcc.Type == 'Member - past ' ) {
con.Relationship_Category_r__c = 'Member - past';
updateCons.add(con);
}
}
update updateCons;
}

joining a table with more than one field in same table

I try to create a join query in Linq. I want to join a table more than one field with same
table. Please see my code below.
var roles = (from ords in _orderRepository.Table
join customers in _customerRepository.Table on ords.CustomerId equals customers.Id
join ordprvrnts in _orderProductVariantRepository.Table on ords.Id equals ordprvrnts.OrderId
join prdvrnts in _productVariantRepository .Table on ordprvrnts.ProductVariantId equals prdvrnts.Id
**join cstevntrle in _customerEventRoleRepository.Table on
new{ customers.Id equals cstevntrle.CustomerId } &&
new { cstevntrle.EventId == model.Event}**
orderby customers.Email ascending
select new CustomerEventRolesModel
{
Customer = customers.Email,
CUstomerId =customers.Id
});
I try to filter customerEventRoleRepository.Table with CustomerId and EventId
how can i do this in this join query.
Please Help.
you have boolean comparisons in your anonymous type definitions...
change your on clause to the following:
join cstevntrle in _customerEventRoleRepository.Table on
new { CustomerId = customers.Id, EventId = model.Event.EventId } equals
new { CustomerId = cstevntrle.CustomerId, EventId = cstevntrle.EventId }
I don't see "model" defined anywhere, so I'm not sure this is going to work, but it should be enough to demonstrate how joins based on multiple fields works - each anonymous class contains the fields from one "side" of the join.

EF Left joining a table on two properties combined with a case statement

I'm trying to write a query for a database that will left join a table to a look up table and the results will be returned based on a case statement.
In normal SQL the query would look like this:
SELECT chis_id, chis_detail, cilt.mhcatID, cilt.mhtID, 'TheFileName' =
CASE
WHEN cilt.mhcatID IS NOT NULL AND cilt.mhtID IS NOT NULL THEN chis_linked_filename
END
FROM chis
LEFT JOIN cilt on cilt.mhcatID = chis.mhcat_id AND cilt.mhtID = chis.mht_id
WHERE cch_id = 50
chis is the table being queried, cilt is a look-up table and does not contain any foreign key relationships to chis as a result (chis has existing FK's to mht and mhcat tables by the mhtID and mhcatID respectively).
The query will be used to return a list of history updates for a record. If the join to the cilt lookup table is successful this means that the caller of the query will have permission to view the filename of any associated files for the history updates.
Whilst during my research I've found various posts on here relating on how to do case statements and left joins in Linq to Entity queries, I've not been able to work out how to join on two different fields. Is this possible?
You need to join on an anonymous type with matching field names like so:
var query = from x in context.Table1
join y in context.Table2
on new { x.Field1, x.Field2 } equals new { y.Field1, y.Field2 }
select {...};
A full working example using the an extra from instead of a join would look something like this:
var query = from chis in context.Chis
from clit in context.Clit
.Where(x => x.mhcatID = chis.mhcat_id)
.Where(x => x.mhtID = chis.mht_id)
.DefaultIfEmpty()
select new
{
chis.id,
chis.detail,
cilt.mhcatID,
cilt.mhtID,
TheFileName = (cilt.mhcatID != null && cilt.mhtID != null) ? chis.linked_filename : null
};
Based on what Aducci suggested, I used a group join and DefaultIsEmpty() to get the results I wanted. For some reason, I couldn't get DefaultIfEmpty() didn't work correctly on its own and the resulting SQL employed an inner join instead of a left.
Here's the final code I used to get the left join working:
var query = (from chis in context.chis
join cilt in context.cilts on new { MHT = chis.mht_id, MHTCAT = chis.mhcat_id } equals new { MHT = cilt.mhtID, MHTCAT = cilt.mhcatID } into tempCilts
from tempCilt in tempCilts.DefaultIfEmpty()
where chis.cch_id == 50
select new {
chisID = chis.chis_id,
detail = chis.chis_detail,
filename = chis.chis_linked_filename,
TheFileName = (tempCilt.mhcatID != null && tempCilt.mhtID != null ? chis.chis_linked_filename : null),
mhtID = chis.mht_id,
mhtcatID = chis.mhcat_id
}).ToList();