I get the following error when I add paging "IQueryable doesn't implement IAsyncQueryProvider" [closed] - asp.net-core

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I want to implement paging for MVC .NetCore application. I have a list " List<_Item> Items which i got from azure blob" I get the following error when I add paging "IQueryable doesn't implement IAsyncQueryProvider"
Paging I'm trying to Implement:
https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page?view=aspnetcore-3.1
Possible solutions I tried looking at:
https://github.com/romantitov/MockQueryable
HomeController: Index function
[Obsolete]
public async Task<IActionResult> Index(string outletId, string contractId, string sort, string currentFilter, int? pageNumber)
{
ViewData["CurrentSort"] = sort;
ViewData["OutletId"] = String.IsNullOrEmpty(sort) ? "descending outletId" : "";
ViewData["ContractId"] = sort == "ContractId" ? "descending contractId" : "ContractId";
if (outletId != null || contractId != null)
{
pageNumber = 1;
}
else
{
outletId = currentFilter;
contractId = currentFilter;
}
blobServices.Add_Tags_on_Blob("GSS_EDM_WorkHistoryTerminationsEngagementsIRP5Request_Dev.csv");
// List<_Item> Items = (List<_Item>)blobServices.Get_BlobItem_List();
List<_Item> Items = (List<_Item>)blobServices.Find_Blob_By_Tag(outletId, contractId);
var records = Items.AsQueryable();
switch (sort)
{
case "descending outletId":
records = records.OrderByDescending(x => x.OutletId);
break;
case "descending contractId":
records = records.OrderByDescending(x => x.ContractId);
break;
case "ContractId":
records = records.OrderBy(x => x.ContractId);
break;
default:
records = records.OrderBy(x => x.OutletId);
break;
}
int pageSize = 3;
return View(await PaginatedList<_Item>.CreateAsync(records, pageNumber ?? 1, pageSize));
// return View(Items.ToPagedList(pageNumber ?? 1, 10));
}
Paging Class[Lines of code with error HomeController
1
Lines of code with error; Pagging Class
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
this.AddRange(items);
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex < TotalPages);
}
}
public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}

According to the error message, we could find The provider for the source IQueryable doesn't implement IAsyncQueryProvider. Only providers that implement IAsyncQueryProvider can be used for Entity Framework asynchronous operations..
We couldn't let List<T>.AsQueryable() to use ToListAsync method, since it doesn't implement the IAsyncQueryProvider.
To solve this issue, you could modify the PaginatedList method's CreateAsync method like below:
public static PaginatedList<T> Create(IQueryable<T> source, int pageIndex, int pageSize)
{
var count = source.Count();
var items = source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
Usage:
return View( PaginatedList<_Item>.Create(records, pageNumber ?? 1, pageSize));

Related

Make [FromQuery] bool testValue accept 'testValue', 'test_value' and 'test-value'

In ASP NET 6+ I need to make [FromQuery] replace underscores _ and minuses - before matching names.
So I want to plumb ASP to allow [FromQuery] bool testValue to be equivalent to all at once:
[FromQuery(Name="testValue")] bool testValue
[FromQuery(Name="test-value")] bool testValue
[FromQuery(Name="test_value")] bool testValue
Is there a place in the pipeline I can get in before names are compared (to remove _ and - myself)?
My current solution is just to replace the Request.Query with my own doctored QueryCollection that duplicates variables with fixed names in a middleware.
But I'm looking for any answer that's more... unhacky?!
public class RequeryMiddleware : IMiddleware
{
private static readonly char[] separators = new[] { '_', '-', '.', '|' };
private static bool Requery(ref string name)
{
bool changed = false;
if (name.IndexOfAny(separators) >= 0)
{
name = string.Concat(name.Split(separators, StringSplitOptions.None));
changed = true;
}
return changed;
}
public Task InvokeAsync(HttpContext context, RequestDelegate next)
{
Dictionary<string, StringValues> mods = new(
StringComparer.OrdinalIgnoreCase
);
foreach (var item in context.Request.Query)
{
string key = item.Key;
if (Requery(ref key))
{
mods.Add(key, item.Value);
}
}
if (mods.Count > 0)
{
Dictionary<string, StringValues> query = new(
context.Request.Query.Count + mods.Count
, StringComparer.OrdinalIgnoreCase
);
foreach (var item in context.Request.Query)
{
query.Add(item.Key, item.Value);
}
foreach (var mod in mods)
{
// if we get here it's bad...
query.TryAdd(mod.Key, mod.Value);
}
// replace the Query collection
context.Request.Query = new QueryCollection(query);
// change the QueryString too
QueryBuilder qb = new(context.Request.Query);
context.Request.QueryString = qb.ToQueryString();
}
return next(context);
}
}

C# - NAudio - How to change sample rate on a float[] while reading it?

I'm coding my first audio application, and I'm struggling for hours on trying to change samplerate of a cached sound.
I'm using NAudio and I was able to change the Volume, tweaking the Read() method of my ISampleProvider.
Here is the CachedSound Class :
public class CachedSound
{
public float[] AudioData { get; private set; }
public WaveFormat WaveFormat { get; set; }
public CachedSound(string audioFileName)
{
using (var audioFileReader = new AudioFileReader(audioFileName))
{
WaveFormat = audioFileReader.WaveFormat;
var wholeFile = new List<float>((int)(audioFileReader.Length / 4));
var readBuffer = new float[audioFileReader.WaveFormat.SampleRate * audioFileReader.WaveFormat.Channels];
int samplesRead;
while ((samplesRead = audioFileReader.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
wholeFile.AddRange(readBuffer.Take(samplesRead));
}
AudioData = wholeFile.ToArray();
}
}
}
And here is the CachedSoundSampleProvider class :
using NAudio.Wave;
using System;
public delegate void PlaybackEndedHandler();
public class CachedSoundSampleProvider : ISampleProvider
{
public event PlaybackEndedHandler PlaybackEnded;
private CachedSound cachedSound;
private long _position;
public long Position {
get { return _position; }
set { _position = value; }
}
private float _volume;
public float Volume {
get { return _volume; }
set { _volume = value; }
}
private float _pitchMultiplicator;
public float PitchMultiplicator
{
get { return _pitchMultiplicator; }
set { _pitchMultiplicator = value; }
}
public WaveFormat OriginalWaveFormat { get; set; }
public WaveFormat WaveFormat {
get { return cachedSound.WaveFormat; }
}
//Constructeur
public CachedSoundSampleProvider(CachedSound _cachedSound)
{
cachedSound = _cachedSound;
OriginalWaveFormat = WaveFormat;
}
public int Read(float[] destBuffer, int offset, int numBytes)
{
long availableSamples = cachedSound.AudioData.Length - Position;
long samplesToCopy = Math.Min(availableSamples, numBytes);
//Changing original audio data samplerate
//Double speed to check if working
cachedSound.WaveFormat = new WaveFormat(cachedSound.WaveFormat.SampleRate*2, cachedSound.WaveFormat.Channels);
Array.Copy(cachedSound.AudioData, Position, destBuffer, offset, samplesToCopy);
//Changing Volume
for (int i = 0; i < destBuffer.Length; ++i)
destBuffer[i] *= (Volume > -40) ? (float)Math.Pow(10.0f, Volume * 0.05f) : 0;
Position += samplesToCopy;
if (availableSamples == 0) PlaybackEnded();
return (int)samplesToCopy;
}
}
I don't know how I can achieve this yet.
My goal is simple, I want to be able to tweak sample rate at realtime.
I read it's impossible to change it on the ISampleProvider interface.
That's why I tried to change it on the original audioData.
Thanks in advance for your help ! :)

Extract common objects from an arraylist

I have a list like shown below. Assume it has 16 Container objects in it. Each Container object is a simple bean, with fields like age, weight, height, etc. How can I create a sub-list that contains common 'Container' objects if a 'Container' object is considered equal if the weight and height are equal?
List<Container> containers = new ArrayList<Container>();
If by "common" containers you mean duplicating ones, then this code might help you:
import java.util.ArrayList;
import java.util.List;
public class CommonContainers {
public static void main(String[] args) {
List<Container> containers = new ArrayList<Container>(16);
for(int i=0; i<13; i++) {
containers.add(new Container(i, i));
}
//add a few duplicating ones
containers.add(new Container(1,1));
containers.add(new Container(5,5));
containers.add(new Container(6,6));
List<Container> sublist = new ArrayList<Container>();
for (Container c1 : containers) {
for (Container c2 : containers) {
if(c1 != c2 && c1.equals(c2)) {
sublist.add(c1);
}
}
}
for (Container c : sublist) {
System.out.println(c);
}
}
private static class Container {
private int weight;
private int height;
#Override
public String toString() {
return String.format("Container[w=%d,h=%d]", weight, height);
}
public Container(int weight, int height) {
this.weight = weight;
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + height;
result = prime * result + weight;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Container other = (Container) obj;
if (height != other.height)
return false;
if (weight != other.weight)
return false;
return true;
}
}
}
If you mean something else or need clarification, please let me know.
Thanks John Smith for giving direction on this question. I used the iterator instead and was able to make a nice solution to what I was looking for. below is the solution. Note that .equals is overriden for the Containers comparison. The technique I used will take the master list and create a sub-list while removing elements from the parent list at the same time. The solution can be called recursivly until you convert the master list into a subset of lists.
public List<Container> extractCommonSubList(
List<Container> masterContainerList) {
List<Container> subList = new ArrayList<Container>();
ListIterator<Container> iterator = masterContainerList.listIterator();
// get first item from master list and remove from master list
Container firstContainer = iterator.next();
iterator.remove();
// Add first container to sublist
subList.add(firstContainer);
while (iterator.hasNext()) {
Container container = iterator.next();
// Search for matches
if (firstContainer.equals(container)) {
// containers are a match, continue searching for matches
subList.add(container);
iterator.remove();
continue;
} else {
break;
}
}
// return common list
return subList;
}

Adding message to faceContext is not working in Java EE7 run on glassFish?

I am doing the tutorial on Java EE7 that comes with glassFish installation. It is also available here. The code is present in glassFish server installation directory
/glassFish_installation/glassfish4/docs/javaee-tutorial/examples/cdi/guessnumber-cdi.
The code works fine as it is. It currently displays correct! when a user correctly guesses the number but does not display failed at end of the game. so I introduced, just one minor change to display the failed message. I have added comments right above the relevant change in code.
Somehow, this change did not help. That is, the at the end of the game, failed message is not displayed.
But the game works as usual. I would like to know why this did not work and how to correct it?
Thanks
public class UserNumberBean implements Serializable {
private static final long serialVersionUID = -7698506329160109476L;
private int number;
private Integer userNumber;
private int minimum;
private int remainingGuesses;
#Inject
#MaxNumber
private int maxNumber;
private int maximum;
#Inject
#Random
Instance<Integer> randomInt;
public UserNumberBean() {
}
public int getNumber() {
return number;
}
public void setUserNumber(Integer user_number) {
userNumber = user_number;
}
public Integer getUserNumber() {
return userNumber;
}
public int getMaximum() {
return (this.maximum);
}
public void setMaximum(int maximum) {
this.maximum = maximum;
}
public int getMinimum() {
return (this.minimum);
}
public void setMinimum(int minimum) {
this.minimum = minimum;
}
public int getRemainingGuesses() {
return remainingGuesses;
}
public String check() throws InterruptedException {
if (userNumber > number) {
maximum = userNumber - 1;
}
if (userNumber < number) {
minimum = userNumber + 1;
}
if (userNumber == number) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Correct!"));
}
//if remainingGuesses is less than or equal to zero, display failed message
//-----------------------------------------------
if (remainingGuesses-- <= 0) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("failed "));
}
return null;
}
#PostConstruct
public void reset() {
this.minimum = 0;
this.userNumber = 0;
this.remainingGuesses = 10;
this.maximum = maxNumber;
this.number = randomInt.get();
}
public void validateNumberRange(FacesContext context,
UIComponent toValidate,
Object value) {
int input = (Integer) value;
if (input < minimum || input > maximum) {
((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("Invalid guess");
context.addMessage(toValidate.getClientId(context), message);
}
}
}
Adding the FacesMessage is actually working, the problem is that you are using postdecrement in your condition.
Postdecrement, as the name suggests, is decremented AFTER the execution of the statement containing the postdecrement.
That means, if you write:
if (remainingGuesses-- <= 0) {
the var remainingGuesses is decremented after the if-condition was evaluated.
In your case, when the last guess is checked, remainingGuesses is actually 1 and therefore the if-condition is not true and the message is not added.
Different obvious solutions:
if (remainingGuesses-- <= 1) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("failed "));
}
or
if (--remainingGuesses <= 0) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("failed "));
}
or
remainingGuesses--;
if (remainingGuesses <= 0) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("failed "));
}
See also:
Is there a difference between x++ and ++x in java?
Difference between i++ and ++i in a loop?

Criteria API - How to get records based on collection count?

I have a Question class in ActiveRecord with following fields:
[ActiveRecord("`Question`")]
public class Question : ObcykaniDb<Question> {
private long id;
private IList<Question> relatedQuestions;
[PrimaryKey("`Id`")]
private long Id {
get { return this.id; }
set { this.id = value; }
}
[HasAndBelongsToMany(typeof(Question), ColumnRef = "ChildId", ColumnKey = "ParentId", Table = "RelatedQuestion")]
private IList<Question> RelatedQuestions {
get { return this.relatedQuestions; }
set { this.relatedQuestions = value; }
}
}
How do I write a DetachedCriteria query to get all Questions that have at least 5 related questions (count) in the RelatedQuestions collection?
For now this gives me strange results:
DetachedCriteria dCriteria = DetachedCriteria.For<Question>()
.CreateCriteria("RelatedQuestions")
.SetProjection(Projections.Count("Id"))
.Add(Restrictions.EqProperty(Projections.Id(), "alias.Id"));
DetachedCriteria dc = DetachedCriteria.For<Question>("alias").Add(Subqueries.Le(5, dCriteria));
IList<Question> results = Question.FindAll(dc);
Any ideas what I'm doing wrong?
Try something like:
var dc = DetachedCriteria.For<Question>()
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("Id")))
.Add(Restrictions.Ge(Projections.Count("RelatedQuestions"), 5))
.SetResultTransformer(new AliasToBeanResultTransformer(typeof(Question)));
var questions = Question.FindAll(dc);