Open zappod opened 1 year ago
Hi zappod!
I did a quick check by replicating your code and for me it seemed to be working properly.
One thing I have had to change is the getter of your property as it gave me a compile error without specifying the template parameter for the GetAttributeValue
method, so the updated code looks like as follows:
[AttributeLogicalName("mot_referedaccount")]
public EntityReference mot_referedaccount
{
get => this.GetAttributeValue<EntityReference>(nameof(mot_referedaccount));
set
{
this.OnPropertyChanging(nameof(mot_referedaccount));
this.SetAttributeValue(nameof(mot_referedaccount), (object)value);
this.OnPropertyChanged(nameof(mot_referedaccount));
}
}
Just like you did, I have filled the new property for only one account:
fakeAccounts[2].mot_referedaccount = new Microsoft.Xrm.Sdk.EntityReference(fakeAccounts[0].LogicalName, fakeAccounts[0].Id);
The following test method returned with a success, the length of the result was one:
[TestMethod]
public void EntityFilter_EmptyFilter_ReferenceWorks()
{
// Create source entity list
var accounts = GetAccountList();
// Define queries to be appled on source
var queryExpression = new QueryExpression();
queryExpression.Criteria.AddCondition("mot_referedaccount", ConditionOperator.NotNull);
// Apply filters on entity list
IEntityFilter<Account> entityFilter = new EntityFilter<Account>();
var filteredResults = entityFilter.FilterBy(accounts, queryExpression);
// Define queries to be appled on source
var queryExpression2 = new QueryExpression();
queryExpression2.Criteria.AddCondition("mot_referedaccount", ConditionOperator.Equal, filteredResults.First().mot_referedaccount);
var filteredResuls2 = entityFilter.FilterBy(accounts, queryExpression2);
Assert.AreEqual(1, filteredResuls2.Count);
}
Could you please check if just updating the getter of your new property would resolve the issue?
By the way, I would recommend you to use an Early Bound Generator tool (if you don't use it yet) such as DLaB.Xrm.EarlyBoundGenerator which can generate you an up-to-date version of the Entities file :)
It looks like ConditionOperator.Equal
operator does not work with non-primitive types such as EntityReference
s. The compiled LINQ reads:
$var1.mot_referedaccount == .Constant<Microsoft.Xrm.Sdk.EntityReference>(Microsoft.Xrm.Sdk.EntityReference)
The LINQ invokes the ==
operator on two EntityReference objects, which performs a reference equality (or opposed to calling the Equals
method) and so always results in false
.
In the example listed above:
// Define queries to be appled on source
var queryExpression2 = new QueryExpression();
queryExpression2.Criteria.AddCondition("mot_referedaccount", ConditionOperator.Equal, filteredResults.First().mot_referedaccount);
var filteredResuls2 = entityFilter.FilterBy(accounts, queryExpression2);
The value in the AddCondition
method is an already existing reference to some EntityReference
object. It succeeds the reference equality.
The following example would likely fail:
// Define queries to be appled on source
var queryExpression2 = new QueryExpression();
queryExpression2.Criteria.AddCondition("mot_referedaccount", ConditionOperator.Equal, new EntityReference(filteredResults.First().mot_referedaccount.LogicalName, filteredResults.First().mot_referedaccount.Id));
var filteredResuls2 = entityFilter.FilterBy(accounts, queryExpression2);
What works is modifying the mot_referedaccount
prop to return a Guid instead of an EntityReference
object. The ==
operator invoked by LINQ works fine with structs.
[AttributeLogicalName("mot_referedaccount")]
public System.Nullable<System.Guid> mot_referedaccount
{
get => this.GetAttributeValue<EntityReference>(nameof(mot_referedaccount))?.Id;
}
Luckily, I do not need setters on such props.
Hi.
Do you know how to make this work for properties of type EntityReference? I added a property to the Account model which is a Entity reference that reffers another account.
property: [AttributeLogicalName("mot_referedaccount")] public EntityReference mot_referedaccount { get => this.GetAttributeValue(nameof (mot_referedaccount));
set
{
this.OnPropertyChanging(nameof (mot_referedaccount));
this.SetAttributeValue(nameof (mot_referedaccount), (object) value);
this.OnPropertyChanged(nameof (mot_referedaccount));
}
}
Then I added this test: [TestMethod] public void EntityFilter_EntityReference() { // Create source entity list var accounts = GetAccountList();
GetAccountList2() looks like this: private List GetAccountList2()
{
var accountFaker = new Faker()
.RuleFor(a => a.accountid, f => f.Random.Guid())
.RuleFor(a => a.name, f => $"{f.Company.CompanyName()} {f.Company.CompanySuffix()}")
.RuleFor(a => a.accountnumber, f => String.Join("", f.Random.Digits(5)))
.RuleFor(a => a.createdon, f => f.Date.Past(1))
.RuleFor(a => a.telephone1, f => f.Phone.PhoneNumber())
.RuleFor(a => a.emailaddress1, f => f.Internet.Email())
.RuleFor(a => a.fax, f => f.Phone.PhoneNumber())
.RuleFor(a => a.donotemail, f => f.Random.Bool())
.RuleFor(a => a.donotfax, f => f.Random.Bool())
.RuleFor(a => a.donotphone, f => f.Random.Bool())
.RuleFor(a => a.preferredcontactmethodcode, f => f.PickRandom());
var list = accountFaker.Generate(2).ToArray();
The entity filter will always return 0 accounts. Any idea why?