Linq query EntityCommandExeceptionException error - c#

When I call 'api/test/name=stop,tap,app...(24 names values)' from the following query below, I am experiencing the an error:
"Message":"An error has occurred.","ExceptionMessage":"Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.","ExceptionType":"System.Data.SqlClient.SqlException
Linq Query:
var data = db.database_bd.AsQueryable();
if (query.startDate != null)
{
data = data.Where(c => c.UploadDate >= query.startDate);
}
// If any other filters are specified, return records which match any of them:
var filteredData = new List<IQueryable<database_bd>>();
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 no filters passed, return all data.
// Otherwise, combine the individual filters using the Union method
// to return all records which match at least one filter.
if (filteredData.Count != 0)
{
data = filteredData.Aggregate(Queryable.Union);
}
if (!data.Any()) //line causing error
{
var message = string.Format("No data was found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
return Request.CreateResponse(HttpStatusCode.OK, data);
}
Query class:
public class Query
{
public string name { get; set; }
public Nullable<DateTime> startDate { get; set; }
public Nullable<DateTime> endDate { get; set; }
}
I tried adding a range to the 'filterdata' method, but I could not get that to work. Any advice, would be very much appreciated.
Thanks

This doesn't work?
var data = db.database_bd.AsQueryable();
if (query.startDate != null)
{
data = data.Where(c => c.UploadDate >= query.startDate);
}
if (!string.IsNullOrEmpty(query.name))
{
var list = query.name.Split(',');
data = data.Where(pr => list.Any(pr2 => pr.Name.Contains(pr2)));
}

I would use predicatebuilder for this (look at doc for "installation").
var data = db.database_bd.AsQueryable();
var mainPredicate = PredicateBuilder.True<database_bd>();
if (query.startDate != null)
mainPredicate = mainPredicate.And(c => c.UploadDate >= query.startDate);
if (!string.IsNullOrEmpty(query.name))
{
var namePredicate = PredicateBuilder.False<database_bd>();
var ids = query.name.Split(',');
foreach (var id in ids) {
namePredicate = namePredicate.Or(c => c.Name != null && c.Name.Contains(id));
}
mainPredicate = mainPredicate.And(namePredicate);
}
data = data.Where(mainPredicate );
if (!data.Any()) //line hopefully causing no more error
{
var message = string.Format("No data was found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}

Related

Get Range on nested collection

I have method that gets data from Db with nested collection
Here is model
public class FilterOptionDto
{
public Guid Id { get; set; }
public string FilterName { get; set; }
public ICollection<OptionDto> Options { get; set; }
}
Here is method that get's data
public async Task<List<FilterOptionDto>?> SetFilterOptions(SetFilterOptionsInputDto input)
{
var useCase = await _dbContext.UseCases.FirstOrDefaultAsync(x => x.Id == input.UseCaseId);
var dimensionsConfiguration =
_analysisDimensionsProvider.AnalysisDimensionsSetting.FirstOrDefault(x => x.FieldNameDomain == input.Name);
if (dimensionsConfiguration != null)
{
var filters = _mapper.Map<List<FilterOptionDto>>(await _dbContext.VwAnalysisUseCaseFilters.Where(x =>
x.JobId == useCase!.JobId && x.IsUseCaseFilter == true && x.FilterType == "multiselect" &&
x.IsAvailable && x.FieldNameDomain == input.Name)
.ToListAsync());
foreach (FilterOptionDto item in filters)
{
item.Options = await GetOptions(useCase?.JobId, dimensionsConfiguration.Source,
dimensionsConfiguration.FieldNameDomain);
}
if (!string.IsNullOrEmpty(input.SearchInput))
{
filters = filters.Where(x => x.Options.Any(x => x.Value.Contains(input.SearchInput))).ToList();
}
// filters = filters.Where(x => x.FilterName.Contains(input.Name)).ToList()
// .GetRange(input.Offset, input.Offset + 3);
return filters;
}
return null;
}
on this line I need to get range on nested collection Options from model, how I can do this?
// filters = filters.********
// .GetRange(input.Offset, input.Offset + 3);
You can chain Select, Skip, and Take.
filters.Select(x => x.Options.Skip(input.Offset).Take(3));

Query SQL Table with Value from MultipleSelectionComboBox

So, I'm using Syncfusion controls and I've a MultipleSelectionCombobox where user can filter multiple arguments.
I have a query which will load a list based on parameters query.
So, first, I have a class to hold my values;
public class Orders
{
public int ID { get; set; }
public string OrderNum { get; set; }
public string Status { get; set; }
public DateTime Date { get; set; }
}
Then, the query:
public IEnumerable<Orders> LoadData()
{
var ctx = new DbContext();
var query = (from o in ctx.tblOrders.AsQueryable()
select new Orders
{
ID = o.OrderID,
OrderNum = o.OrderNum.ToString(),
Status = o.OrderStatus,
Date = o.OrderDate
});
if(CmbOrderStatus.SelectedItems != null)
{
List<string> list = new List<string>();
foreach (SelectedItems obj in CmbOrderStatus.SelectedItems)
{
list.Add(obj.ToString());
}
for(int i = 0; i < list.Count; i++)
{
var value = list[i];
query = query.Where(p => p.Status == value);
}
}
return query.ToList();
}
So, in Database in have many Orders and many OrderStatus, like "Opened", "Delayed", "Closed".
So, if I filter in CmbOrderStatus "Opened" and "Delayed", I get nothing! If only one is selected, I get nothing!
Any help here?
Thanks
The code use only last filter.
Try this:
public IEnumerable<Orders> LoadData()
{
var ctx = new DbContext();
var query = (from o in ctx.tblOrders.AsQueryable()
select new Orders
{
ID = o.OrderID,
OrderNum = o.OrderNum.ToString(),
Status = o.OrderStatus,
Date = o.OrderDate
});
if(CmbOrderStatus.SelectedItems != null)
{
List<string> list = new List<string>();
foreach (SelectedItems obj in CmbOrderStatus.SelectedItems)
{
list.Add(obj.ToString());
}
query = query.Where(p => list.Contains(p.Status));
}
return query.ToList();
}

c# - web.api - try to build a new return value

I'am learning c# and angular and I try to aggregate the data of a product with the follower. I have some NotMapped-fields in my class (codefirst)
[NotMapped]
public string followitemtitle { get; set; }
[NotMapped]
public string followitemprice { get; set; }
And I get 2 items of each group
return _context.Product
.Include(c => c.productgroup)
.GroupBy(p => p.productgroupid)
.SelectMany(g => g.OrderByDescending(p => p.productdate).Take(2));
What I try is a loop and build a new return-value -> only the first product ( every second in the list) - with some information of the follower product.
[HttpGet("new")]
public IActionResult GetProductsIncFollower()
{
var productEntities = _productrepository.GetProductsIncFollower();
Product tmpData = new Product();
IEnumerable<Product> tmpDataList = new List<Product>();
int index = 1;
string tmpFollowtitle = "";
string tmpFollowprice = "";
foreach (var item in productEntities)
{
if(index % 2 != 0)
{
tmpFollowtitle = item.title;
tmpFollowprice = item.price;
}
else
{
tmpData = item;
tmpData.followitemtitle = tmpFollowtitle;
tmpData.followitemprice = tmpFollowprice;
tmpDataList.Append(tmpData);
}
index++;
}
var results = tmpDataList;
return Ok(results);
}
But tmpDataList is empty and I dont understand why.

Entity framework use between with strings

I realy stucked with my function. I have table and I'm using EF. Representation for this table in ORM is:
public partial class ProductAttributes
{
public long Id { get; set; }
public System.Guid AttrId { get; set; }
public System.Guid ProdId { get; set; }
public string Value { get; set; }
public virtual Attributes Attributes { get; set; }
public virtual Products Products { get; set; }
}
This table contains FK to products and Attributes. Main responsibility of this table is to keep value for specified product and attribute. As you can see value represented as string.
Users on web site using sliders sets range for values. Now I should get all products from DB where values between users choice. Also a choose can be not range, just single value represented as a string. And here I got stuck.
Here function for selecting values from DB:
// Dictionaries Guid - attributeID , string[] - values from slider
public IEnumerable<Products> GetFilteredProducts(Dictionary<Guid, string[]> searchParam)
{
List<Products> list = new List<Products>();
try {
entityContext = new SiteDBEntities();
IQueryable<Products> query = entityContext.Products;
foreach (var item in searchParam)
{
//check do we have single value, it's mean that we whould search equals value
if (item.Value.Length == 1)
{
var r = item.Value[0];
query = query.Where(x => x.ProductAttributes
.Any(y => y.AttrId == item.Key && y.Value.Equals(r)));
}
else
{
double a = Double.Parse(item.Value[0]); // min value
double b = Double.Parse(item.Value[1]); // max value
//AND HERE BECOMES BIG PROBLEMS
// this code will throw error becuase ToDouble cannot be converted to T-SQl
// query = query.Where(x => x.ProductAttributes
// .Any(y => y.AttrId == item.Key
// && Convert.ToDouble(y.Value) > a
// && Convert.ToDouble(y.Value) < b));
//this will return error cannot conver string to double
// query = query.Where(x => x.ProductAttributes
// .Any(y => y.AttrId == item.Key
// && (double)y.Value > a
// && (double)y.Value < b));
// this will return error 'cannot apply ">" to IEnumerable<double>'
// query = query.Where(x => x.ProductAttributes.
// Any(y => y.AttrId == item.Key
// && y.Value.Cast<double>() > a
// && y.Value.Cast<double>() < b));
// }
// this monster that I found on stackoverflow will return an error 'a lambda expression with body cannot be converted to expression tree'
// query = query.Where(x => x.ProductAttributes.Any(p =>
// {
// double val = 0;
// if (double.TryParse(p.Value, out val))
// {
// return p.AttrId == item.Key &&
// val >= a &&
// val <= b;
// }
// else
// {
// return false;
// }
// });
}
}
catch(Exception){}
}
Maybe someone alredy faced with this issue and can help me? Here my slider:

Cannot Convert Type Void to Generic List

I have two lists: a list of countries and a list of jobs
public List<Countries> getSharedCountries(string brandName)
{
var items = SharedJobs.Where(a => a.BrandName == brandName);
var items2 = items.OrderBy(a => a.CountryCode);
Countries = new List<Countries>();
string Country = null;
foreach (var item in items2)
{
if (Country != item.CountryCode)
{
Country = item.CountryCode;
Countries.Add(new Countries() { CountryCode = item.CountryCode, JobIDs = getSharedJob(item.CountryCode) });
}
}
return Countries;
}
public void getSharedJob(string Country)
{
var items = SharedJobs.Where(a => a.CountryCode == Country);
JobNetDetails = new List<JobDetail>();
CareerBoardDetails = new List<JobDetail>();
JobSharkDetails = new List<JobDetail>();
JobServeDetails = new List<JobDetail>();
int AusCount = 0;
foreach (var item in items)
{
if (Country == "AUS")
{
AusCount++;
if (AusCount % 4 == 0)
{
JobNetDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
else
{
JobServeDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
}
}
}
On the line where I am accessing the method getSharedJob, it errors and gives me the error, cannot implicitly convert void to system.generic.List?
I am very confused as to why this is happening?
As the signature of your method states, public void getSharedJob(string Country) it's void, so it doesn't return anything, you should change it and return the list you wish.
Edit: As I read in the comments you need to return 4 Lists.
You have several options:
You can return an array of Lists;
You can return a List of Lists;
You can return your own class containing the 4 Lists.
Try below code which returns jobDetails from the method you are calling
public List<Countries> getSharedCountries(string brandName)
{
var items = SharedJobs.Where(a => a.BrandName == brandName);
var items2 = items.OrderBy(a => a.CountryCode);
Countries = new List<Countries>();
string Country = null;
foreach (var item in items2)
{
if (Country != item.CountryCode)
{
Country = item.CountryCode;
foreach (var jobDetail in getSharedJob(item.CountryCode))
{
Countries.Add(new Countries() { CountryCode = item.CountryCode, JobIDs = jobDetail.JobID });
}
}
}
return Countries;
}
public List<JobDetail> getSharedJob(string Country)
{
var items = SharedJobs.Where(a => a.CountryCode == Country);
JobNetDetails = new List<JobDetail>();
CareerBoardDetails = new List<JobDetail>();
JobSharkDetails = new List<JobDetail>();
JobServeDetails = new List<JobDetail>();
int AusCount = 0;
foreach (var item in items)
{
if (Country == "AUS")
{
AusCount++;
if (AusCount % 4 == 0)
{
JobNetDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
else
{
JobServeDetails.Add(new JobDetail() { JobPageTitle = item.JobPageTitle, JobID = item.JobID, JobUrl = item.JobUrl });
}
}
}
return JobServeDetails;
}
Your method signature says take a string variable and return nothing (void).
public void getSharedJob(string country)
JobIDs is expecting a value
JobIDs = getSharedJob(item.CountryCode)
so you need to return a value which matches the JobIDs type which I assume is a List of ints or a List of JobDetails.

Categories

Resources