EF Dynamic Filters delegate expression - entity-framework

We are using EF Dynamic filters (ASP.NET MVC 5 app)
https://entityframework-dynamicfilters.net/overview
The filter below is working, but set only once.
builder.Filter("IMultiOrganization", (IMultOrganization d) => ((d.TenantId == GlobalAppVariables.IssuerId) && (d.IsShared == true)) || ((d.IsShared == false && d.AzureObjIdentifier == GlobalAppVariables.AzureObjIdentifier)));
The variables 'IssuerId' and 'AzureObjIdentifier' are dynamic session variables, those are changing all the time. This causes problems and I would like the filter to use those variables straight from the session.
According to the documentation this is caused because this filer isn't a delegate expression.
Filters can be defined on a specific entity class or an interface by providing a specific value, e.g. an IsDeleted filter created on an ISoftDelete interface which will automatically filter those entities by applying the condition "IsDeleted==false".
Filter values can also be provided via a delegate/expression instead of a specific value which allows you to change the parameter value dynamically. For example, a filter can be created on the UserID and provided per HTTP request.
We also use delegate filters what indeed is working fine.
builder.EnableFilter("IMultiTenant", () => GlobalAppVariables.AzureObjIdentifier != null || GlobalAppVariables.IssuerId != Guid.Empty);
But I can't get the first filter work as a delegate expression and need a bit help on that.

I found the solution by using parameters within the filter.
First of all I changed the filter which now supports parameters.
builder.Filter("IMultiOrganization", (IMultiOrganization d, Guid tenantId, string azureId) => (d.TenantId == tenantId && d.IsShared == true) || (d.AzureObjIdentifier == azureId && d.IsShared == false), GlobalAppVariables.IssuerId, GlobalAppVariables.AzureObjIdentifier);
Then I call method below in the db context constructor
private void SetMultiOrganizationFilterParams()
{
if (GetFilterEnabled("IMultiOrganization"))
{
this.SetFilterScopedParameterValue("IMultiOrganization", "azureId", GlobalAppVariables.AzureObjIdentifier);
this.SetFilterScopedParameterValue("IMultiOrganization", "tenantId", GlobalAppVariables.IssuerId);
}
}
Source: https://github.com/zzzprojects/EntityFramework.DynamicFilters#changing-filter-parameter-values

Related

Subquery checking for next elements

I am currently working on a Database-Security-System, have to make sure that in the next two minutes of this database there is no other entry that equals to true. But somehow I always end up getting a System.NotSupportedException.
My Code
public IQueryable<AuthorizationAttempt> GetSuspiciousActivity(
DateTime from,
DateTime to)
{
return GetActivity(from, to).Where(e1 =>
e1.Result == false
&& !GetActivity(
e1.AttemptDate,
e1.AttemptDate.AddMinutes(2d)
).Any(e2 => e2.Result == true));
}
Error
System.NotSupportedException: "LINQ to Entities does not recognize the method 'System.DateTime AddMinutes(Double)' method, and this method cannot be translated into a store expression."
Thanks a lot
You can't use any helper methods inside your LINQ query. Use DbFunctions instead.

Richfaces 4 dynamic select options when user type

I am using rich faces select component.
I want dynamic values when user manually type some thing in the select component.
<rich:select enableManualInput="true" defaultLabel="start typing for select" value="#{supplierSearchBean.userInput}">
<a4j:ajax event="keyup" execute="#this" listener="#{supplierSearchBean.userInputChange}"/>
<f:selectItems value="#{supplierSearchBean.selectOptions}" />
</rich:select>
Java code as follows
public void userInputChange(ActionEvent ae){
Map map = ae.getComponent().getAttributes();
System.out.println(map.toString());
}
public void setUserInput(String userInput) {
System.out.println("userINput = " + userInput);
this.userInput = userInput;
}
Here i found 2 issues
1st: setUserINput always print empty string when user type value
2nd: listener method never get call.
any help ?
The problem is most probably that there is no selected value while the user types, and this component restricts the allowed values to the specified select items. A partial input is thus not valid and cannot be bound to your bean.
I think you could get the expected behavior if you use a rich:autocomplete instead. However, if you want to restrict the allowed values, maybe you can keep your rich:select and listen for the selectitem event.
Override getItems function in richfaces-utils.js file in richfaces-core-impl-4.0.0.Final.jar under richfaces-core-impl-4.0.0.Final\META-INF\resources folder.
Change the condition of pushing items to be
if(p != -1)
instead of
if(p == 0)
This should fix the issue.

ConfigurationElement—Combination of Attributes?

Say I have defined a custom AdapterElement : ConfigurationElement with properties Type, Name and Version. Since Name and Version uniquelly identifies the Type property, I would like to enforce the configuration file to have one of the following structures:
<adapter type="TypeOfAdapter"/>
<adapter name="NameOfAdapter" version="VersionOfAdapter"/>
I could easily mark those three properties with IsRequired = false and let users specify the combination the want. However, the following combinations are not valid and I would like to forbid them:
<adapter type="TypeOfAdapter" version="VersionOfAdapter"/>
<adapter type="TypeOfAdapter" name="NameOfAdapter"/>
Is there any easy way of achieving this?
I had to do a bit of reading around to find answers on this one.
How about adding a PostDeserialise check for validity to your AdapterElement class?
protected override void PostDeserialize()
{
bool isValid = Type != null && Name == null && Version == null
|| Type == null && Name != null && Version != null;
if (!isValid)
{
throw new ArgumentException("Must specify either Type or Name and Version");
}
base.PostDeserialize();
}
According to a blog I found there is no more obvious way of verifying validity of Multiple Attributes on a single configuration section - but it appears to be true for configuation elements too.

Unable to create a constant value of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid') are supported in this context

I'm using MVC and Entity Framework. I've created a class in my model folder with this code below. I keep getting the error message above with both queries below. I know there is a known issue on referencing non-scalar variables, but I'm not sure how to implement a workaround:
http://msdn.microsoft.com/en-us/library/bb896317.aspx#Y1442
private MovieLibraryDBEntities movieLibraryDBEntitiesContext;
public int getNumberOfEntriesReserved()
{
return (from m in movieLibraryDBEntitiesContext.Movies
where m.CheckedOut.Equals(1)
select m).Count();
//return movieLibraryDBEntitiesContext.Movies
// .Where(e => e.CheckedOut.Equals(1))
// .Select (e => e.Title).Count();
}
You cannot use m.CheckedOut.Equals(1) in linq-to-entities query. Use m.CheckedOut == 1 but CheckedOut must be integer.
This is an older question. I had the same problem when trying to filter a nullable column using the IQueryable interface. I solved the problem by first checking to see if the object had a value and then checking the value.
widgets = widgets.Where(x => x.ID.HasValue.Equals(true) && x.ID.Value.Equals(widgetID));
same issue using Any()
i had to change my where clause to search on primitive types, for me int
so this
where order.User == user
becomes this
where order.User.UserId == user.UserId
There is a blog post explaining the quirk.

Zend Framework: is there a way to access the element name from within a custom validator?

I'm writing a custom validator that will validate against multiple other form element values. In my form, I call my custom validator like this:
$textFieldOne = new Zend_Form_Element_Text('textFieldOne');
$textFieldOne->setAllowEmpty(false)
->addValidator('OnlyOneHasValue', false, array(array('textFieldTwo', 'textFieldThree')));
My validator will check that only one of those three fields (textFieldOne, textFieldTwo, textFieldThree) has a value. I want to prevent a future developer from accidentally passing the same field twice.
$textFieldOne->addValidator('OnlyOneHasValue', false, array(array('textFieldOne', 'textFieldTwo', 'textFieldThree')));
So far, my validator works perfectly, except when I pass the same field name as the field that has the valiator set on it.
In my validator, you can see that I am checking that the value (of the element with the validator set on it). I'm also checking the values of the other fields that were passed to the validator.
public function isValid($value, $context = null) {
$this->_setValue($value);
$this->_context = $context;
if ($this->valueIsNotEmpty()) {
if ($this->numberOfFieldsWithAValue() == 0) {
return true;
}
$this->_error(self::MULTIPLE_VALUES);
return false;
}
if ($this->numberOfFieldsWithAValue() == 0) {
$this->_error(self::ALL_EMPTY);
return false;
}
if ($this->numberOfFieldsWithAValue() == 1) {
return true;
}
if ($this->numberOfFieldsWithAValue() > 1) {
$this->_error(self::MULTIPLE_VALUES);
return false;
}
}
private function valueIsNotEmpty() {
return Zend_Validate::is($this->_value, 'NotEmpty');
}
private function numberOfFieldsWithAValue() {
$fieldsWithValue = 0;
foreach ($this->_fieldsToMatch as $fieldName) {
if (isset($this->_context[$fieldName]) && Zend_Validate::is($this->_context[$fieldName], 'NotEmpty')) {
$fieldsWithValue++;
}
}
return $fieldsWithValue;
}
My solution is to either...
A. Let the developer figure out there is a certain way to do it.
B. Ignore $value, forcing you to pass all the elements (which isn't much different than the first option).
or C. (if possible) Find the name of the element that called my validator in the first place and ignore it from the list of $fieldsWithValue.
I don't think there is a way to apply a validator on a form without attaching it to an element, but that would be even better, if it were an option.
How can I solve this problem?
Normaly i'd advise against such things, but, in this case I believe a static member in your class would actually provide a good solution to this problem.
With a static member, you can set it to the value in the first time the isValid is called, and check against it in subsequent calls, thus giving you a mechanism for this.
You may want to set this up to use some array in the configuration options, so that you can namespace and allow multiple instances of the validator to exist happily alongside each other for different sets.
The only problem that you really have to decide how to overcome, is where you wish to display the error, as yes the form itself does not take validators. if you want all the duplicates after the first to display an error, it is not so much of a problem.