Dynamics CRM Plugin - LINQ Query in 'Pre Validation' - dynamics-crm-2011

I have a Dynamics CRM Plugin registered in "Pre Validation" and trigger on delete.
I have inside it a LINQ query that retrieve the maximum value of a date field of children records for a particular parent record.
Here is my code:
var q = (from e1 in serviceContext.CreateQuery<entity1>()
join e2 in serviceContext.CreateQuery<entity2>() on e1.typeid.Id equals e2.codeId
where e1.statecode == 0 && e1.ParentId.Id.Equals(new Guid(ParentGuidStr))
orderby e1.dt descending
select new {e1.dt, e2.code}).ToList();
I am getting the following error on the above query When the record that the plugin triggers on is INACTIVE:
PreValidateEntity1Delete PlugIn Error:
System.Reflection.TargetInvocationException: Exception has been thrown
by the target of an invocation. ---> System.ArgumentNullException:
Value cannot be null. Parameter name: g
I am NOT sure why I am getting the above error and if the link between an inactive children record and a parent record got broken in a LINQ query or there is another reason.

First, please ensure all children records have reference to parent record.
Then, change your where contidion into:
where e1.statecode == 0 && e1.ParentId != null && e1.ParentId.Id.Equals(new Guid(ParentGuidStr))
The problem is that an EntityReference field (e1.ParentId) may be null and when you tried access a null entity, the error appears.
Then because of that, you should also make sure e1.typeid is not null in the join condition too.
Or, you can try a workaround with 2 separate queries, and collect information from their results.
Good luck!

Related

How to trigger an action when deleting value from an autocomplete field on Apex 18.2

I have created an autocomplete item on my page and i want to trigger the change on this field. I am using Apex 18.2 and for the autocomplete item i have used a dynamic action with event Update [Text field with autocomplete].
This works fine when i change the value from the autocomplete and put another value from the list, but if i want to delete the value, the DA is not triggered.
I have tried also ojupdate custom event, but the same problem.
I have tried event change when item is null, but no success.
What i want to do is when deleting the value from the item (when item is null) to trigger an action.
Is there a DA that can help me on this particular issue?
Item: P37_ART
Type: Text field with autocomplete
Settings: Contains & Ignore Case
Lazy Loading: YES
Maximum values in List: 20
Item based on SQL Query and the format is number1||' - '||text1
Example: 1245 - Groceries
Dynamic Action:
Event: Update [Text field with autocomplete]
Action: Execute Javascript code
alert('test');
create another dynamic action thats has client side condition type javascript condition and check if your Text field is empty or is null using JS code, for example:
document.getElementById("textfield").value == "" || document.getElementById("textfield").value.length == 0 || document.getElementById("textfield").value== null

How to fetch rows based on CRM modifiedon column

I need to pull all rows from an entity which were modified recently. I am using the following statement which gives me an error
from e in myEntity
where e.ModifiedOn.HasValue
select e.cust_name
The error states
Invalid 'where' condition. An entity member is invoking an invalid property or method.
Message Invalid 'where' condition. An entity member is invoking an invalid property or method.
Try with:
from e in myEntity
where e.ModifiedOn != null
select e.cust_name
Using Lambda Expressions:
var getModified = myEntity.where(w=>w.ModifiedOn!=null).select(s=>s.cust_name);

Saving to a Entity that has Many To Many relationship

I have a set of tables (ConditionTemplate and KeyWord) that have a many to many relationship. In code I am trying to add a Keyword to a specific ConditionTemplate record. Unfortunately, when I think I'm adding a Keyword to a specific condition I'm getting an error as if it's adding a new Keyword without being associated to a condition.
An Image of my Model:
My Code:
Global Variables Creation:
EnterpriseEntities EE;
ConditionTemplate myConditionTemplate;
Load Global Variables:
EE = new EnterpriseEntities();
EE.Database.Connection.ConnectionString = Myapp.EnterpriseEntityConnectionString;
myConditionTemplate = EE.ConditionTemplates.Where(c => c.TemplateCode == "17D").FirstOrDefault();
The above code loads a single Condition with Many Keywords.
Available Keywords are in a listbox and the user pushed a button to select a keyword(s) to move to the condition. This is the code that handles that.
foreach (KeyWord SelectedKeyWord in ListBoxAvailableKeyWords.SelectedItems)
{
KeyWord NewKeyWord = new KeyWord
{
KeyWordID = SelectedKeyWord.KeyWordID,
ID = SelectedKeyWord.ID,
Word = SelectedKeyWord.Word
};
myConditionTemplate.KeyWords.Add(NewKeyWord);
}
Then the user pushes a button to save changes and I call
EE.SaveChanges
Then I get this error:
System.Data.UpdateException: An error occurred while updating the
entries. See the inner exception for details. --->
System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint
'IX_KeyWord'. Cannot insert duplicate key in object 'dbo.KeyWord'. The
duplicate key value is (ADJUDICATION). The statement has been
terminated.
If I remove the code that sets the word property (Word = SelectedKeyWord.Word
) when I create the keyword object I get this error.
System.Data.Entity.Validation.DbEntityValidationException: Validation
failed for one or more entities. See 'EntityValidationErrors' property for more details.
Which tells me the word field is required.
In order to tell EF that the KeyWords you selected already exist in the database and to avoid the problem you must attach them to the context:
foreach (KeyWord SelectedKeyWord in ListBoxAvailableKeyWords.SelectedItems)
{
KeyWord NewKeyWord = new KeyWord
{
// You actually only need to set the primary key property here
ID = SelectedKeyWord.ID
};
EE.KeyWords.Attach(NewKeyWord);
myConditionTemplate.KeyWords.Add(NewKeyWord);
}
Edit
If the KeyWord entities are already attached to your context (because they have been loaded before with the same context for example) you can use instead:
foreach (KeyWord SelectedKeyWord in ListBoxAvailableKeyWords.SelectedItems)
{
KeyWord NewKeyWord = EE.KeyWords.Find(SelectedKeyWord.ID);
myConditionTemplate.KeyWords.Add(NewKeyWord);
}

In a master detail relationship how to get a list of master entities without detail entities crm 2011?

I'm using CRM 2011 and I have a 1-n relationship between EntityA(master) and EntityB(detail).
I need to get the list of EntityA records that are not related to any EntityB records. How can I accomplish this inside a plugin using query expression?
I believe this should work (See the EDIT, it doesn't work):
var qe = new QueryExpression("entitya");
var entityBLink = qe.AddLink("entityb", "entityaid", "entityaid", JoinOperator.LeftOuter);
entityBLink.LinkCriteria.AddCondition("entitybid", ConditionOperator.Null);
It should create a SQL Statement that looks something like this:
SELECT
FROM entitya
LEFT OUTER JOIN entityb on entitya.entityaid = entityb.entityaid
AND ( entityb.entitybid IS NULL )
EDIT - Working version
var qe = new QueryExpression("entitya");
var entityBLink = qe.AddLink("entityb", "entityaid", "entityaid", JoinOperator.LeftOuter);
entityBLink.Columns.AddColumn("entitybid");
var entities = service.RetrieveMultiple(qe).Entities.
Where(e => !e.Attributes.Keys.Any(k => k.EndsWith(".entitybid"))).
Select(e => e.ToEntity<entitya>());
The SQL statement for the first query does get generated as is, but since the null check is on the join and it is a left join, all EnityA entities get returned.
The bad news is in CRM there is no way to perform a sub query, or specify in the where clause, a linked entity's properties. I really hope Microsoft spends some time with the next major release adding this type of functionality.
You can however perform the filter on the client side, which is what the C# code is doing above.

Tell EF to handle a composite index that is unique

I set a 3-column index that must be unique in my table. How can I tell EF that? I'm currently getting a DbUpdateException when trying to save the changes.
Cannot insert duplicate key row in object 'sm.SkillAssignations' with unique index 'IX_SkillAssignations'. The duplicate key value is (8285, 1, 2, 2).\r\nThe statement has been terminated.
In order to avoid the exception check if an entity with the unique index value you want to insert already exists:
if (!context.SkillAssignations.Any(s =>
s.Value1 == newSkillAssignation.Value1 &&
s.Value2 == newSkillAssignation.Value2 &&
s.Value3 == newSkillAssignation.Value3))
context.SkillAssignations.Add(newSkillAssignation);
else
// your own error handling
// - or do you want to UPDATE the existing entity in this case?
It could still fail if someone else inserts an entity with that key between the Any call (EXISTS query) and the Add (INSERT statement). I am not aware of any magic that would save you this check.

Resources