Fix issue in CodeEffects editor return error in MVC - rule-engine

I have issue when filter data using filter editor, I'm using object(order) to get data
I get this error :
System.NotSupportedException: 'Cannot compare elements of type 'System.Collections.Generic.ICollection`1[[CodeEffects.Rule.Asp.Demo.Entities.Order, CodeEffects.Rule.Asp.Demo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'. Only primitive types, enumeration types and entity types are supported.'
enter image description here

The Entity Framework no longer, if it ever did, supports comparison of related tables with null. The CodeEffects probably needs to adjust their code to account for it.
As a workaround, set EvaluationParameters.PerformNullChecks = false as in:
EvaluationParameters evps = new EvaluationParameters
{
LINQProviderType = LinqProviderType.Entities,
PerformNullChecks = false
};
You pass those parameters in the Evaluator's constructor.
Note, this will disable all null-checks, which may or may not be a problem in your particular case.

Related

JPA entity modified by reflection not merged by entity manager

I need to check if my actual entity is different from the old one.
I use reflection because my method must be standardized.
For each column, I update the value if and only if it's not null (because i read it from a CSV and a column may be not specified).
for(Field column : fields){
column.setAccessible(true);
Object newValue = column.get(myObject);
if( newValue != null && !newValue.equals(column.get(oldObject))){
column.set(oldObject, newValue);
}
}
this.entitymanager.merge(oldObject)
If I do the changes like that, no UPDATE query is done.
If I change the value in the normal way oldobject.setValue(newValue) the query is done and the record is updated.
Why no UPDATE query is done by the entity manager if I change value via reflection?
Just find some good information about such behaviour at this :
By default when using weaving/agent EclipseLink uses attribute change
tracking to detect changes. This will not detect changes made through
reflective field access (method access is ok though).
You can change the default using the #ChangeTracking annotation to
deferred which will detect change made through reflection. i.e.
#ChangeTracking(ChangeTrackingType.DEFERRED)
You could also disable weaving, or weaving of change tracking in the
persistence.xml using, "eclipselink.weaving.changetracking"="false"
So there are couple of solutions that can try :
Use reflective method access
Change the ChangeTracking to deferred or even disable it
Disable weaving
Thank to #Ken Chan answer, I correct the method using getters and setters.
for(Field column : columns){
Method mSet = myclass.getMethod("set"+ StringUtils.capitalize(column.getName()), column.getType());
Method mGet = myclass.getMethod("get"+ StringUtils.capitalize(column.getName()));
Object newValue = mGet.invoke(articolo);
if( newValue != null && !newValue.equals(mGet.invoke(old))){
mSet.invoke(old, newValue);
}
}
I must pay attention to methods' name. If entity have the property description, there must be also getDescription() and setDescription().
Now it works

Lookup Edit binding

I have a model written using Entity Framework Code First called Project.
In my UI, there is a page called ProjectEdit as shown in the image below. As seen in the image below, Customer and BOMs are Lookup Edit.
I'm trying to load Customer and BOMs to Lookup Edit but it's not working. Below is my code.
//New
if (entity == null)
{
Entity = new Project();
}
//Edit
else
{
ProjectCodeTextEdit.DataBindings.Add("EditValue", entity, "ProjectCode");
DescriptionTextEdit.DataBindings.Add("EditValue", entity, "Description");
CustomerLookUpEdit.DataBindings.Add("EditValue", entity, "CustomerId");
BOMsLookUpEdit.DataBindings.Add("EditValue", entity, "BOMs");
}
Below is my LookUpEdit Properties.
Generally LookUpEdit object's data binding is not implemented the same way as a TextEdit object's. While in TextEdits's case you just need to assign the variable value to EditValue property (I suppose your TextEdits binding work fine, isn't it?), with LookUp Edit you should assign variables to ValueMember and a DisplayMember properties of the object. That is why we usually display data rows with LookUpEdit objects, where ValueMember is the identification field of the row and DisplayMember is the field of the row whose value you wish to be displayed.
In your case you should be more clear about what you wish to display in your lookupedits. Each Project instance has one Customer property and many BOMs, right? So CustomerLookUpEdit will show one record and BOMsLookUpEdit a list of values according to the Project object that was chosen for edit, correct? I suppose that both your Customer and BOM classes have some kind of ID property and description property of their own. In this case you should bind these values to the LookUpEdits. eg. in your initialization function code add these lines
CustomerLookUpEdit.Properties.DataSource = entity.Customer;
CustomerLookUpEdit.Properties.ValueMember = "someCustomerIDpropertyName" ;
CustomerLookUpEdit.Properties.DisplayMember = "someCustomerDescriptionpropertyName";
BOMsLookUpEdit.Properties.DataSource = entity.BOMs;
BOMsLookUpEdit.Properties.ValueMember = "someBOMIDpropertyName" ;
BOMsLookUpEdit.Properties.DisplayMember = "someBOMDescriptionpropertyName" ;
You can read more in this topic https://documentation.devexpress.com/#WindowsForms/clsDevExpressXtraEditorsLookUpEdittopic
When we are adding entities to a List, we have to take care of our DataSource if is a DBContext or a DBSet, each one has implications in the compiler, that was your case, in this case you had to especify your DataSource like a DBSet and get the Entities
Add<TEntity>(TEntity entity)
The type parameter omitted is posible because the compiler will infer it.

How to filter Exact Online accounts on their classification code?

I am trying to make a list of how much accounts have a certain classification1 code (which currently ranges from 1 to 7).
when accessing the API (which makes use of OData) I get the following error:
No property 'Code' exists in type 'System.Nullable`1[[System.Guid,
mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=*********]]' at position 16.
My url looks like this:
https://start.exactonline.nl/api/v1/*/crm/Accounts?$inlinecount=allpages&$top=0
but when I add a filter it gives the error.
https://start.exactonline.nl/api/v1/*/crm/Accounts?$inlinecount=allpages&$top=0&$filter=Classification1/Code eq '1'
The API I access is found here:
https://start.exactonline.nl/docs/HlpRestAPIResourcesDetails.aspx?id=9
https://start.exactonline.nl/docs/HlpRestAPIResourcesDetails.aspx?id=7
Is there an easier was to receive all the different count values or to fix the filter?
Unfortunately that is not possible. Classification1 is a Guid, not an object with the properties of a classification.
If you want to filter on the classification code, you first have to retrieve the Guid of the classification, and then filter on the Guid.
So first:
/api/v1/{division}/crm/AccountClassifications?$filter=Code eq 'yourCode'&$select=ID
And then, using the result of the previous call:
/api/v1/{division}/crm/Accounts?$filter=Classification1 eq guid'the-guid-you-retrieved'

Getting the column name (sspace) from an ospace property name

I can see from the following example how to get the table name of an OSpace type:
https://lowrymedia.com/2014/06/10/ef6-1-mapping-between-types-tables-including-derived-types/
But how do I go about getting the SSpace column name from an OSpace property name (i.e. CLR type property)?
By browsing the MetadataProperties from the corresponding CSpace property, I can see there is a "Configuration" entry containing the column name if changed using the Fluid API or ColumnAttribute, but the value of the entry is an internal class on EF's part. Is it at all possible?
I have browsed a few answers regarding this topic, but none of them take into account the Fluid API configuration.
P.S. the specific property I'm looking for is scalar, if that can simplify things...
Column Name
To get the column name, you have to first get the EdmProperty associated with that column in the “structural space” (SSpace). I provide code to do that below. Once you have the EdmProperty, the name of the column is simply EdmProperty.Name:
string GetColumnName(DbContext context, PropertyInfo property) {
return GetStructuralSpaceEdmProperty(context, property).Name;
}
Structural Space Property
This is based on an article. That article gives you enough information to map all the way to the structural EntityType. I added a bit at the end to do the actual property mapping to get the EdmProperty representing the column. As the article states, these APIs require ≥EntityFramework-6.1.
EdmProperty GetStructuralSpaceEdmProperty(DbContext context, PropertyInfo property) {
IObjectContextAdapter adapter = context;
var metadata = adapter.ObjectContext.MetadataWorkspace;
// First, you map the Object Space to the Conceptual Space.
var objectItemCollection = (ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace);
var objectEntityType = metadata.GetItems<EntityType>(DataSpace.OSpace)
.Single(oet => objectItemCollection.GetClrType(oet) == property.DeclaringType);
// Note: we are assuming that CSpace and OSpace name their properties the
// same instead of trying to use EF’s own OSSpace mappings here.
var conceptualEntityType = metadata.GetItems<EntityType>(DataSpace.CSpace)
.Single(cet => objectEntityType.Name == cet.Name);
var conceptualEdmProperty = conceptualEntityType.Properties
.Single(ep => ep.Name == property.Name);
// Then you map the conceptual space onto the structural space.
var entitySet = metadata.GetItems<EntityContainer>(DataSpace.CSpace)
.Single().EntitySets
.Single(es => es.ElementType.Name == conceptualEntityType.Name);
var entityMapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.Single().EntitySetMappings
.Single(esm => esm.EntitySet == entitySet);
// The entity may be split to different tables or fragments.
var fragments = entityMapping.EntityTypeMappings
.SelectMany(etm => etm.Fragments);
var propertyMappings = fragments.SelectMany(f => f.PropertyMappings);
// Normal properties will be “ScalarPropertyMapping”.
// Depending on what information you are seeking or your
// model, you may be interested in other PropertyMapping.
var structuralSpaceProperty = propertyMappings
.OfType<ScalarPropertyMapping>()
.Single(pm => pm.Property == conceptualEdmProperty).Column;
return structuralSpaceProperty;
}
Note that once you have EdmProperty in structural space, there are a bunch of other useful properties you can read from it. For example, for SQL Server, EdmProperty.IsUnicode will be true for NVARCHAR/NCHAR and false for VARCHAR/CHAR types whereas this property is not set to a useful value in the conceptual space.
Random Information
Spaces in EF
Alex D. James’s blog post “Tip 10 — How to understand Entity Framework jargon” explains some of the terms of the API which do not make sense on their own. DataSpace.OSpace stands for “Object Space”, meaning the .net POD classes. DataSpace.SSpace stands for “Structural Space”, probably named after “structured” in the term “SQL” and thus meaning it most directly describes the backend database. DataSpace.CSpace stands for “Conceptual Space” which seems intended to be a neutral space which both the “Object Space” and “Structural Space” can map into. DataSpace.OCSpace stands for the mapping from the object space onto the conceptual space. We bypass this mapping because we assume that property names in the object space are the same as in our .net types. DataSpace.CSSpace stands for the mapping of conceptual space onto structural space. We use this mapping because the model may be configured to use a different column name via the fluent API or ColumnAttribute.
API Confusion
The metadata API of EF seems to assume that the consumer of the API has an understanding of the internals of EF to an extent. It is not made in a very type safe way which helps consumers. For example, the fact that we had to use Enumerable.OfType<TResult> to get to ScalarPropertyMapping means that one has to know to expect the collection to have ScalarPropertyMapping instances in it. Likewise, the MetadataWorkspace.GetItems<T>() method requires us to know that the sorts of items one would find in the metadata include EntityType. Thus, a deep understanding of the internals of EF or complete examples are necessary to write code that consumes the mapping portion of these APIs.

Breeze property validation using data annotations in entity framework

Within my entity framework model I have:
<Required(), Range(0, Double.MaxValue, ErrorMessage:="Weight must be numeric and cannot be negative")> _
Public Property Weight() As Double
<Required(), Range(0, Double.MaxValue, ErrorMessage:="Recycled content must be numeric and between 0 and 100")> _
Public Property RecycledContent() As Double
And in my viewmodel I have:
if (!editComponent().entityAspect.validateProperty("recycledContent")) {
/* do something about errors */
var msg = 'Recycled content is invalid!';
logger.logError(msg, error, system.getModuleId(lt_articleEdit), true);
}
And yet when I enter a value greater than 100 (in the recycled content field) it still passes validation somehow! I have used the script debugger to step through and in the breeze validation routine there are two validators registered which are "required" and "number" but nothing that I can see mentions the range.
Can breeze do range validation? All I'm trying to do is pick up a data validation error based on metadata from the data annotations of the model and use this to trigger a client-side highlight on the field in error and log an error message.
It's a very reasonable request but we aren't quite there yet.
Right now Breeze doesn't YET pick up Range validations from Entity Framework metadata. Please vote for this on the Breeze User Voice . This matters because we do prioritize our work based on this venue.