The entity instance here is getting a list of 10 arrays from which I need to get the value of invalid Dir.
var entityInstance = FacadeServiceContext.LoadEntityBaseInstances(entityName, searchParams, context: null).ToList();
if (entityInstance != null && entityInstance.Any())
{
var invalidDirflag = entityInstance.Where(item => item.Equals(CustomConstants.ICMInvalidDIR));
foreach (var item in entityInstance )
{
if( invalidDirflag.Equals(false))
{
var filters = new Dictionary<string, List<string>>();
addHeaderFilters(filters, request);
addLineItems(filters, (JArray)request[SourcingConstants.ClientSoCoApplicableDocumentsAttributesItemsFieldName]);
coAppDocs.AddRange(filterDeterminedDocuments(entityInstance, filters));
}
}
}
I get an exception with the above code:
Enumeration yielded no results
How do I do this?
Linq Function "Where" could return empty iteration.
Check your code line 4. Plus, "Where" Function does not return bool type.
I recommend to use "FirstOrDefault()" on line 4. If iteration is empty, variable invalidDirflag will be set to false.
See below code.
var entityInstance = FacadeServiceContext.LoadEntityBaseInstances(entityName, searchParams, context: null).ToList();
if (entityInstance != null && entityInstance.Any())
{
var invalidDirflag = entityInstance.Where(item => item.Equals(CustomConstants.ICMInvalidDIR)).FirstOrDefault();
foreach (var item in entityInstance )
{
if( invalidDirflag.Equals(false))
{
var filters = new Dictionary<string, List<string>>();
addHeaderFilters(filters, request);
addLineItems(filters, (JArray)request[SourcingConstants.ClientSoCoApplicableDocumentsAttributesItemsFieldName]);
coAppDocs.AddRange(filterDeterminedDocuments(entityInstance, filters));
}
}
}
Related
I want to paginate through records in a dynamo table using a lastEvaluatedKey. How can I use the scanfilter to use the lastEvaluatedKey to begin the next request at that given location?
public List<Record>? GetRecords(Request request)
{
// Define marker variable
Dictionary<string, AttributeValue> startKey = null!;
var records = new List<Record>();
do
{
// Issue request
Condition cond = new Condition();
cond.ComparisonOperator = "NULL";
cond.AttributeValueList = new List<AttributeValue>() { };
var scanFilter = new Dictionary<string, Condition>() { { "ExecutedTime", cond } };
var allEvents = client.ScanAsync("rRecords", scanFilter).Result; //Dictionary<string, Condition> scanFilter
// View all returned items
List<Dictionary<string, AttributeValue>> items = allEvents.Items;
foreach (Dictionary<string, AttributeValue> item in items)
{
//do stuff
}
// Set marker variable
startKey = allEvents.LastEvaluatedKey;
} while (startKey != null && startKey.Count != 0);
return scheduledEventRecords;
}
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html I have tried this approach but those APIs (.Scan on the AmazonDynamoDBClient) are not available the version AWSSDK 3.5.1.20 that I am currently using.
I code below that works well with an API for the DataTables plugin; for each column that the DataTables searches in, regardless of type, the filter works as expected based on what is supplied.
DataTables also has a "Global" search feature where you can search in one field and if there is a match in ANY of the rows for said data then a match is returned.
What I am Hoping For:
A way to perform a search on an IEnumerable such that if any of the fields match the search the result is returned.
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
var generalSearch = nvc["sSearch"];
if (!string.IsNullOrWhiteSpace(generalSearch))
{
var generalSearchProperties = typeof(T).GetProperties();
foreach (var currentProperty in generalSearchProperties)
{
Type propType = currentProperty.PropertyType;
set = set.Where(StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType));
/* ^^^^^ */
/*
Instead of the "Where" here I am looking for something like "where or" which can be added to the IEnumerable.
*/
}
}
Original Code:
protected virtual IQueryable<T> FilterEntitiesBySearchParameters(IQueryable<T> set)
{
try
{
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
var props = typeof(T).GetProperties();
foreach (var prop in props)
{
var name = prop.Name;
var val = nvc[name];
Type propType = prop.PropertyType;
if (val != null)
{
set = set.Where(StaticUtility.PropertyEquals<T>(prop, val, propType));
}
if (nvc.GetPairs().Where(p => p.Value == name).Where(p => p.Key.StartsWith("mDataProp")).Any())
{
var key = nvc.GetPairs().Where(p => p.Value == name).Where(p => p.Key.StartsWith("mDataProp")).FirstOrDefault().Key;
key = key.Replace("mDataProp", "sSearch");
val = nvc[key];
if (!String.IsNullOrEmpty(val))
set = set.Where(StaticUtility.PropertyEquals<T>(prop, val, propType));
}
}
return set;
} catch (Exception exc)
{
return set;
}
}
If I understand your request correctly, you basically want to search through your data and match any field for equality? If that's true, then simply add your matching data to a new set, and filter it by .Distinct() after the fact, to make sure you get one record of each. Something like so...
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
var results = new IEnumerable<T>();
var generalSearch = nvc["sSearch"];
if (!string.IsNullOrWhiteSpace(generalSearch))
{
var generalSearchProperties = typeof(T).GetProperties();
foreach (var currentProperty in generalSearchProperties)
{
Type propType = currentProperty.PropertyType;
results.AddRange(set.Where(StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType)));
}
}
return results.Distinct();
You could try to first create a BinaryExpression consisting of all the different options, then pass that expression to the Where() method of the query.
Assuming your StaticUtility class is used to create expressions, you might try something like the following:
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
// Container for filter expression
BinaryExpression filter = null;
var generalSearch = nvc["sSearch"];
if (!string.IsNullOrWhiteSpace(generalSearch)) {
var generalSearchProperties = typeof(T).GetProperties();
foreach (var currentProperty in generalSearchProperties) {
Type propType = currentProperty.PropertyType;
if (filter == null) {
// Start with first filter expression
filter = StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType);
} else {
// Add another filter using OR
BinaryExpression other = StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType);
filter = BinaryExpression.OrElse(filter, other);
}
}
}
// Add actual filter to query
set = set.Where(filter);
private String[] GetProperties(EContent_EcontentFields eContentField)
{
List<String> list = new List<String>();
Type fieldType = eContentField.GetType();
var properties = fieldType.GetProperties();
foreach (var prop in properties)
{
if (prop.MemberType == MemberTypes.Property)
{
if (prop.PropertyType.IsGenericType)
{
dynamic items = prop.GetValue(eContentField, null);
foreach (var item in items)
{
Type typeItem = item.GetType();
list.Add(item);
}
}
}
}
return list.ToArray();
}
This is my method to retrieve an array of strings with the properties of my entity but the statement:
if (prop.PropertyType.IsGenericType)
It's always false.
I've copy-pasted the code so maybe I'm missing something. Something that I can't see.
var result = new List<string>();
var type = eContentField.GetType();
foreach (var prop in type.GetProperties())
{
result.Add(prop.Name);
}
return result.ToArray();
}
This is about twice faster than your method, if you are interested in speed.
Ps: if you change the foreach into a for loop, it wil be a bit faster, but not a lot :)
I found a solution to retrieve all the property names.
private String[] GetProperties(EContent_EcontentFields eContentField)
{
List<String> list = new List<String>();
Type type = eContentField.GetType();
var properties = type.GetProperties().Where(x => x.MemberType == MemberTypes.Property).Select(x => x.Name);
foreach (var item in properties)
{
if(item != null)
list.Add(item.ToString());
}
return list.ToArray();
}
Im my model I have decleared value from wich I have to group, like this:
Note! Sender value is multivalued type
private ICollection<string> _send;
[SolrField("sender")]
public ICollection<string> Sender
{
get
{
if (_send == null)
{
return new Collection<string> { "" };
}
else
{
return _send;
}
}
set { _send = value; }
}
In my controller where I call Linq group code is:
var groups = matchingSpremenljivke.GroupBy(s => s.Sender);
foreach (IGrouping<string, SolrVariables> groups in gruph)
{
...
}
In foreach sentence I get this error:
"Unable to cast type 'Grouping
[System.Collections.Generic.ICollection'1
[Sytem.String],MySoulution.Models.SolrVariables]'to type
'System.Linq.IGrouping'2[System.String,MySolution.Models.SolrVariables]'
This error shows only for variables that are multivalued, for non-multivalued type of variables this error is not shown.
my all code look like this now:
var grupe = matchingSpremenljivke.GroupBy(s => s.Sender);
foreach (IGrouping<ICollection<string>, SpremenljivkeSolr> grupa in grupe)
{
List<SpremenljivkeSolr> tmpList = new List<SpremenljivkeSolr>();
foreach (SpremenljivkeSolr tmpSolr in grupa)
{
tmpList.Add(tmpSolr);
}
SpremenljivkeSolr spremenljivkeSolr = new SpremenljivkeSolr();
spremenljivkeSolr.Internal = tmpList[tmpList.Count - 1].Internal;
spremenljivkeSolr.Exchangetimestamp = tmpList[tmpList.Count - 1].Exchangetimestamp;
spremenljivkeSolr.Order = tmpList[0].Order;
spremenljivkeSolr.Exchangetimestamp2 = tmpList[0].Exchangetimestamp;
spremenljivkeSolr.MsgT = tmpList[0].MsgT;
spremenljivkeSolr.Sender = tmpList[tmpList.Count - 1].Sender;
seznam.Add(spremenljivkeSolr);
}
Thanks for help!
Since the type of Sender property is ICollection<string>, this query:
var groups = matchingSpremenljivke.GroupBy(s => s.Sender);
returns an IGrouping<ICollection<string>,SolrVariables> not IGrouping<string, SpremenljivkeSolr>. Change string to ICollection<string> in foreach or use var.
Also are you sure you want to group your values based on an ICollection<T> without providing an IEqualityComparer<T> implementation ?
I am able to filter the data with the following two parameters id1 and id2, and get accurate result of 10 records, from which have 9 with a price_type=cs and other with price-type=ms.
However, if I add price_type to the parameters id1 and id2 (id1=23456,567890&id2=6782345&price_type=ms), I get 3000 records instead of getting one record.
Am I missing something in the code. Any help would be very much appreciated.
var data = db.database_BWICs.AsQueryable();
var filteredData = new List<IQueryable<database_Data>>();
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.Name != null && c.Name.Contains(i)));
}
}
if (!string.IsNullOrEmpty(query.id2))
{
var ids = query.id2.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.ID2!= null && c.ID2.Contains(i)));
}
}
if (!string.IsNullOrEmpty(query.id1))
{
var ids = query.id1.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.ID1!= null && c.ID1.Contains(i)));
}
}
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
foreach (string i in ids)
{
filteredData.Add(data.Where(c => c.Type.Contains(i)));
}
}
if (filteredData.Count != 0)
{
data = filteredData.Aggregate(Queryable.Union);
}
Updated Code:
var data = db.database_BWICs.AsQueryable();
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
data = data.Where(c => c.Name != null && ids.Contains(c.Name));
}
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
data = data.Where(c => ids.Contains(c.Cover));
}
if (!String.IsNullOrEmpty(query.id1))
{
var ids = query.id1.Split(',');
data = data.Where(c => c.ID1!= null && ids.Contains(c.ID1));
}
Because you don't add filter to restrict, every filter adds datas to result.
It means you make OR between your filters, not AND.
And your usage of contains looks rather strange too : you're using String.Contains, while I would guess (maybe wrong) that you want to see if a value is in a list => Enumerable.Contains
You should rather go for something like this (withoud filteredData)
var data = db.database_BWICs.AsQueryable();
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
data = data.Where(c => c.Name != null && ids.Contains(c.Name)));
}
//etc.
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
data = data.Where(c => ids.Contains(c.Type));
}
EDIT
Well, if you wanna mix and or conditions, you could go for PredicateBuilder
Then your code should look like that (to be tested).
//manage the queries with OR clause first
var innerOr = Predicate.True<database_BWICs>();//or the real type of your entity
if (!String.IsNullOrEmpty(query.id1))
{
var ids = query.id1.Split(',');
innerOr = innerOr.Or(c => c.ID1!= null && ids.Contains(c.ID1));
}
if (!String.IsNullOrEmpty(query.id2))
{
var ids = query.id2.Split(',');
innerOr = innerOr.Or(c => c.ID2!= null && ids.Contains(c.ID2));
}
//now manage the queries with AND clauses
var innerAnd = Predicate.True<database_BWICs>();//or the real type of your entity
if (query.price_type != null)
{
var ids = query.price_type.Split(',');
innerAnd = innerAnd.And(c => ids.Contains(c.Type));
}
//etc.
innerAnd = innerAnd.And(innerOr);
var data = db.database_BWICs.AsQueryable().Where(innerAnd);