Entity Framework LINQ query - sql-server

I would like to know how to change this entity framework linq query.
I have tableA with the following columns: project (varchar), code (varchar), assess (integer)
the codes data are hierarchical -- i.e 10011, 10012, 10013 ..etc are children of code 1001. Another example 123001, 123002, 12300, 12301 are children of code 1230.
I want query based on project and then go through every rows of code and retrieve all it children with assessment = 0 (for example)
I wrote the below code but it is not giving the correct result:
var result = db.tableA.AsQueryable();
var tempResult = result.Where(p => p.project.Equals(ProjectValue));
result = tempResult.Where(c => c.Code.StartsWith(c.Code) && c.assess== 0);
The query above is not returning the children of the codes where project equal 'ProjectValue'

You need to know which records are the parents in order to do this, if not your condition StartsWith will always be true since you have the children and the parent in tempResult.
I'll assume that the codes with the minimum length are the parents.
After you select the parents you just take all the records that start with the parent code but have different lengths than the parent codes.
var result = db.tableA.AsQueryable();
var minLength = result.Select(t => t.Code.Length).Min();
var tempResult = result.Where(p => p.project.Equals(ProjectValue) && p.Code.Length == minLength);
result = result.Where(c => tempResult.Any(d => c.Code.StartsWith(d.Code)) && c.assess== 0 && c.project.Equals(ProjectValue) && c.Code.Length != minLength);

The closest thing I can think of right now, with the amount of context you've given in your question will end up being:
var result = db.tableA.AsQueryable();
var tempResult = result.Where(p => p.project.Equals(ProjectValue)).select(p => p.code);
result = result.Where(c => tempResult.contains(c.Code.substring(0, 4)) && c.assess== 0 && c.project.Equals(ProjectValue));

Related

Get specific columns on an Included Entity: Invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'

One of my linked tables PropertyInfo has an image column, which I don't want to retrieve, every time I .Include() that table. Therefore I took the following approach:
user = _context.Users.Where(x => x.Id == idOfUser)
.Include(x => x.Co.PropertyInfo.Select(i =>
new PropertyModel(
Id = i.Id,
Date = i.Date,
CompanyNumber = i.CompanyNumber,
LinkedCategories = i.LinkedCategories,
LinkedReviews = i.LinkedReviews)))
.ThenInclude(x => x.LinkedCategories)
.ThenInclude(x => x.LinkedReviews)))
.Take(1)
.FirstOrDefault()
This code throws an error:
The expression [EXPRESSION I PASTED ABOVE] is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'....
Is it possible that I'm trying to assign the linked Tables like LinkedCategories and LinkedReviews which are being ThenInclud-ed? Or is this related to something else? How can I include entities without querying for all of the columns?
Maybe something like this if you have an empty constructor in PropertyModel.
You definitely can make it with single query. I don't know what is the structure of your models. For more accurate answer, you can share them.
user = _context.Users.Where(x => x.Id == idOfUser)
.Select(i => new PropertyModel
{
Id = i.PropertyInfo.Id,
Date = i.PropertyInfo.Date,
CompanyNumber = i.PropertyInfo.CompanyNumber,
LinkedCategories = i.PropertyInfo.LinkedCategories,
LinkedReviews = i.PropertyInfo.LinkedReviews
})
.Take(1)
.FirstOrDefault()

Using .Filter When the Filter Criteria are in Pre-existing String (TypeScript/Node.js)

I'm trying to process an array of JSON objects that have various common attributes, filtering each array entry on one or more of those attributes.
Normally, I'd just do it something like this:
let filteredResultsArray = originalArray.filter((obj) => {
return obj.attribute1 <= 3 && obj.attribute2 > 0 && obj.attribute3 === 10;
});
My problem is that the filter parameters (the part after "return" in the code above) are highly variable (and unpredictable) from run to run, so I can't hard-code them in the filter. I compute them on the fly and store the whole thing in a string in my code. For example, on one run it might be:
myAttributeString = "obj.attribute1 <= 3 && obj.attribute2 > 0 && obj.attribute3 === 10";
I've tried doing this:
let filteredResultsArray = originalArray.filter((obj) => {
return myAttributeString;
});
That's failing to filter anything. Apparently .filter() is not properly interpreting what I've stored in myAttributeString as filter criteria.
I have a sneaking suspicion that eval(myAttributeString) might be one way to pull this off, but unfortunately I'm working on a team where we've got tslint set to disallow the use of eval(), so that's not an option.
Anybody have an idea how I can get this to work?
When you "compute them on the fly", instead of creating a string, create a callback function that you can then pass to filter. For example, instead of
const myAttributeString = "obj.attribute1 <= 3 && obj.attribute2 > 0 && obj.attribute3 === 10";
do
const filterCallback = obj => obj.attribute1 <= 3 && obj.attribute2 > 0 && obj.attribute3 === 10
Then, later, when the appropriate time comes to .filter, simply pass that as the callback:
const filteredResultsArray = originalArray.filter(filterCallback);
If you can't pass functions around, another option would be to build an array of conditions, for example
[
{
prop: "attribute1",
constraint: "<=",
value: 3
},
{
prop: "attribute2",
constraint: ">",
value: 0
},
// ...
]
and then turn the object into the filter function needed.
****************************************UPDATE******************************
As I suspected, eval() did work, but since I can't use it in my delivered code, and thanks to CertainPerformance's suggestion (which put my thinking on the right track) as well as the Node.js documentation site (via a lucky Google search), I was able to find a workaround using the vm module:
import * as vm from "vm";
let filteredResultsArray = originalArray.filter(
vm.runInThisContext("(obj) => {
return " + myAttributeString + ";}"));
Case closed.

Apply Filter to Column with Numeric Values

I have a solution for filtering on this question.
This works perfectly with a column that has string values. When I try to filter a column with numeric values it will not work. I'm assuming it is because .setHiddenValues() will not accept numeric values. I could be wrong.
Let me explain my scenario:
The user inputs a value on an HTML interface, let's say 6634.
The HTML calls my function on .gs and passes the numeric value the user inputted.
google.script.run //Executes an Apps Script JS Function
.withSuccessHandler(updateStatus) //function to be called upon successfull completion of Apps Script function
.withFailureHandler(failStatus)
.withUserObject(button) //To pass the event element object
.projectSearch2(projectID); //Apps Script JS Function
return;
The function (on the linked question above) will take that value and bump it up against the values in a column deleting the value if it is found. What I am left with is an array of values that I do not want filtered.
function projectSearch2(projectID){
var ss = SpreadsheetApp.getActive();
var monthlyDetailSht = ss.getSheetByName('Data Sheet');
var monLastCN = monthlyDetailSht.getLastColumn();
var monLastRN = monthlyDetailSht.getLastRow();
var data = monthlyDetailSht.getRange(1,1,1,monLastCN).getValues();//Get 2D array of all values in row one
var data = data[0];//Get the first and only inner array
var projectIDCN = data.indexOf('Project Id') + 1;
//Pull data from columns before filtering
var projectIDData = monthlyDetailSht.getRange(2,projectIDCN,monLastRN,1).getValues();
//Reset filters if filters exist
if(monthlyDetailSht.getFilter() != null){monthlyDetailSht.getFilter().remove();}
//Start Filtering
var projectIDExclCriteria = getHiddenValueArray(projectTypeData,projectID); //get values except for
var rang = monthlyDetailSht.getDataRange();
var projectIDFilter = SpreadsheetApp.newFilterCriteria().setHiddenValues(projectIDExclCriteria).build();//Create criteria with values you do not want included.
var filter = rang.getFilter() || rang.createFilter();// getFilter already available or create a new one
if(projectID != '' && projectID != null){
filter.setColumnFilterCriteria(projectIDCN, projectIDFilter);
}
};
function getHiddenValueArray(colValueArr,visibleValueArr){
var flatUniqArr = colValueArr.map(function(e){return e[0];})
.filter(function(e,i,a){return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1); })
return flatUniqArr;
}
That array is used in .setHiddenValues() to filter on the column.
Nothing is filtered however. This works for all columns that contain string values, just not columns with numeric values. At this point I'm lost.
Attempted Solutions:
Convert user variable to string using input = input.toString(). Did not work.
manually inserted .setHiddenValues for projectIDExclCriteria. Like this: var projectIDFilter = SpreadsheetApp.newFilterCriteria().setHiddenValues([1041,1070,1071,1072]).build(); That succeeded so I know the issue is before that.
Step before was calling getHiddenValueArray. I manually inserted like so: var projectIDExclCriteria = getHiddenValueArray(projectIDData,[6634]); It is not working. Is the issue with that getHiddenValueArray function not handling the numbers properly?
Here is a solution. Changing the following:
.filter(function(e,i,a){return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1); })
To:
.filter(function(e,i,a){return (a.indexOf(e) == i && visibleValueArr.indexOf(e) == -1); })
That works! Thank you Tanaike. The next question is will this impact columns that are not numeric. I have tested that and it works as well.
How about this modification?
From :
.filter(function(e,i,a){return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1); })
To :
.filter(function(e,i,a){return (a.indexOf(e) == i && visibleValueArr.indexOf(e) == -1); })
Note :
In this modification, the number and string can compared using each value.
If you want to use return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1), you can achieve it by modifying from colValueArr.map(function(e){return e[0];}) to colValueArr.map(function(e){return e[0].toString();}).
In this modification, colValueArr.map(function(e){return e[0].toString();}) converts the number to string, so the number is used as a string.
Reference :
Array.prototype.indexOf()

Query different levels in database laravel

Good day. Am trying to query my database to get the child of a child of a child. Every user has 2 children. Am using query builder. The requirements is not to use eloquent and eloquent relationships. But am struggling with it.
$firstchild= DB::table('users') - >where('parent_id', Auth::user() ->id) -> get() ;
$secondchild1 = DB::table('users') - >where('parent_id', $firstchild[0]->parent_id) -> get() ;
$secondchild2 = DB::table('users') - >where('parent_id', $firstchild[1]parent_id) -> get() ;
return view('home' ['firstchild' => $firstchild, 'secondchild1 ' => $secondchild1, 'secondchild2 ' => $secondchild2 , ])
It returns undefined offset 0 if the user child has no child. How do i do it if i want to get without any errors.
If I want to get the children of those children the query results gave, how will I do so?
Try this:
$firstchild = DB::table('users')->where('parent_id', Auth::user()->id)->get();
if ($firstchild->count() == 2) { //**Contains exactly 2 arrays inside the 'firstchild' collection.
$secondchild1 = DB::table('users')->where('parent_id', $firstchild[0]->parent_id)->get();
$secondchild2 = DB::table('users')->where('parent_id', $firstchild[1]->parent_id)->get();
}
return view('home', compact('firstchild', 'secondchild1', 'secondchild2'));
Hope it's helpful.

Sitecore Solr Search result items matching count

I am using Sitecore Solr search for searching using a keyword string, Is there a way to know the number of matches for each of the returned result items?.
The following is the code I am using:
using (var context = Index.CreateSearchContext())
{
List<Item> ResultList = new List<Item>();
var contentPredicate = PredicateBuilder.True<customSearchResultItem>();
contentPredicate = contentPredicate.And(p => p.Content.Contains(SearchKey));
contentPredicate = contentPredicate.And(p => p.Name != "__Standard Values");
var languagePredicate = PredicateBuilder.True<customSearchResultItem>();
languagePredicate = languagePredicate.And(p => p.Language == Context.Language.Name);
var CombinPredicates = PredicateBuilder.True<customSearchResultItem>();
CombinPredicates = CombinPredicates.And(languagePredicate);
CombinPredicates = CombinPredicates.And(contentPredicate);
// execute the search
IQueryable<customSearchResultItem> query = context.GetQueryable<customSearchResultItem>().Where(CombinPredicates);
var hits = query.GetResults().Hits;
}
From what I know, you can not get the number of matches for every result item based on the keyword used for search. What you can get, is a score value from Solr.
var hits = query.GetResults().Hits;
foreach (var hit in hits)
{
var score = hit.Score;
}
This is the value for the whole query, so it includes all predicates like language, not Standard Values and keywords in your case.
Remember, that this value can be different if you use Solr and if you use Lucene - this is dependent on the internal calculations.
I solved this by adding boosting values to each predicate then the for each result item I got the score and divide it by .59 which in my case the maximum value that occurs when all predicates staesfied; The code in details can be found on the following blog post:
http://sitecoreinfo.blogspot.com/2015/10/sitecore-solr-search-result-items.html

Resources