Paging property missing in Status - linq-to-twitter

In latest version of LINQ to Twitter v2.1.08 there is no longer support for paging. How do I get a certain page without page property?
Cheers
int curPageIndex=5;
string pageindex="5";
string cmd = "next";
using (var twitterCtx = new TwitterContext(myauth))
{
try
{
// set up the "main query"
IQueryable<Status> test = from tweet in twitterCtx.Status select tweet;
switch (cmd)
{
case "prev":
test = pageindex.Length > 0
? test.Where(p => p.Type == StatusType.Home && p.Page == curPageIndex)
: test.Where(p => p.Type == StatusType.Home);
break;
case "next":
test = pageindex.Length > 0
? test.Where(p => p.Type == StatusType.Home && p.Page == curPageIndex)
: test.Where(p => p.Type == StatusType.Home);
break;
default:
//
test = test.Where(p => p.Type == StatusType.Home);
break;
}

Solution: Changed Page parameter to SinceID and MaxID
//Get the statusids in the query, add or subtract so you skip current id's
ulMaxId = test.Min(status => ulong.Parse(status.StatusID)) - 1;
ulSinceID = test.Max(status => ulong.Parse(status.StatusID)) + 1;
//Return ID above and use them in future calls (below)
//Now you can navigate timelines, depending if you are stepping forward or backwards
? test.Where(p => p.Type == StatusType.Home && p.SinceID == ulong.Parse(sinceid)
...
? test.Where(p => p.Type == StatusType.Home && p.MaxID == ulong.Parse(maxid))

Related

LinqKit Core PredicateBuilder not functioning correctly

I have this query:
var query = LinqKit.PredicateBuilder.New<Resume>();
if (selectedWorkFieldID != 0)
{
query = query.And(js => js.WorkFieldID == selectedWorkFieldID);
if (!(selectedJobIDs.Contains(0) && selectedJobIDs.Count() == 1))
{
foreach (int jobID in selectedJobIDs)
query = query.Or(js => js.JobID == jobID);
}
}
var finalQuery = context.Resumes.AsNoTracking().Include(r => r.ResumeSkills)
.ThenInclude(rs => rs.Skill).Include(r => r.JobSeeker).ThenInclude(r => r.Profile)
.AsExpandable().Where(query);
count = finalQuery.Count();
resumes = finalQuery.Skip(args.Skip.Value).Take(args.Top.Value).ToList<Resume>();
This query returns All resumes not filtered ones. When I debug, the debugger curser enters the foreach block that filters with or, and there is one jobID in selectedJobIDs but the query returns all resumes. it seems the predicate builder not working at all. How to solve this?
I changed code to this:
if (selectedWorkFieldID != 0)
{
query = query.And(js => js.WorkFieldID == selectedWorkFieldID);
if (!(selectedJobIDs.Contains(0) && selectedJobIDs.Count() == 1))
{
var query2 = LinqKit.PredicateBuilder.New<Resume>();
foreach (int jobID in selectedJobIDs)
query2 = query2.Or(js => js.JobID == jobID);
query.And(query2);
}
}
and it is corrected.

Null reference exception in linq select statement

I am getting a null reference exception from my bellow linq query. I have a table with an entityID(reference to another table to get translated text), but in some case i don't have proper translated text in my child table. This case i need to take lookupName field text and assign to lookupName field.
await _context.FormLookup.Where(x=>!(x.isDeleted))
.Select(x => new LookupList() {
lookupID = x.lookupID,
TransilatedName = _context.TranslatedText.FirstOrDefault(z => z.entityID == x.entityID && z.languageId == language && !(z.isDeleted)).languageText,
lookupName = x.lookupName,
itemCount = x.lookupDetails.Count(),
parent = x.parentID
}).ToListAsync();
I need to add a condition like
TransilatedName = _context.TranslatedText.FirstOrDefault(z => z.entityID == x.entityID && z.languageId == language && !(z.isDeleted)) != null ? TransilatedName = _context.TranslatedText.FirstOrDefault(z => z.entityID == x.entityID && z.languageId == language && !(z.isDeleted)).languageText : x.lookupName,
Any suggestions?
Select property LanguateText before you use FirstOrDefault:
var query = dbContext.FormLookup
.Where(x=>!(x.isDeleted))
.Select(x => new LookupList()
{
lookupID = x.lookupID,
TransilatedName = dbContext.TranslatedText
.Where(translatedText => translatedText.entityID == x.entityID
&& translatedText.languageId == language
&& !translatedText.isDeleted)
.Select(translatedText => translatedText.languageText)
.FirstOrDefault(),
...
});

LINQ: query very slow

I have the following database structure (just showing the pertinent tables):
I need to get a listing of all the elements in the table "Propietario" and each element must have a list of all its related elements in "Clave". Specifically, I need the field "CodigoClave" from "Clave".
Also, I need to be able to filter the results any of the fields.
This is what I've come up with so far:
int pageSizeP = (pageSize == null || pageSize == 0 || pageSize > 15) ? 15 : (int)pageSize;
int pageNumberP = (pageNumber == null || pageNumber == 0) ? 1 : (int)pageNumber;
var propietariosCount = context.Propietarios.Count();
var propietariosQuery = context.Propietarios
.AsEnumerable()
.OrderBy(p => p.Nombre).ThenBy(p => p.Apellido1).ThenBy(p => p.Apellido2)
.Select(p => new
{
Id = p.Id,
Nombre = p.Nombre,
Apellido1 = p.Apellido1,
Apellido2 = p.Apellido2,
NIF = p.NIF,
Claves = string.Join(", ", context.PropietariosFincas
.Where(pf => pf.PropietarioId == p.Id)
.Join(context.Expedientes
.Include(e => e.Clave),
pf => pf.FincaId,
e => e.FincaId,
(pf, e) => (e.Clave.CodigoClave + ((e.Clave.Alias == null) ? "" : " - " + e.Clave.Alias))
).Distinct().ToList())
// Getting an array of Claves would do;
// I could turn it into a string in the JS app
// But it's just as slow
});
if (criteriosBusqueda != "")
{
string[] aCriterios = criteriosBusqueda.Split(new string[] { "," }, StringSplitOptions.None);
CompareOptions compareOptions = CompareOptions.IgnoreCase;
if (aCriterios[0] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Nombre != null)
.Where(p => p.Nombre.Replace("/", "__").ContainsIgnoreAccents(aCriterios[0], compareOptions));
if (aCriterios[1] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Apellido1 != null)
.Where(p => p.Apellido1.Replace("/", "__").ContainsIgnoreAccents(aCriterios[1], compareOptions));
if (aCriterios[2] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Apellido2 != null)
.Where(p => p.Apellido2.Replace("/", "__").ContainsIgnoreAccents(aCriterios[2], compareOptions));
if (aCriterios[3] != "")
propietariosQuery = propietariosQuery
.Where(p => p.NIF != null)
.Where(p => p.NIF.Replace("/", "__").ToLower().Contains(aCriterios[3].ToLower()));
if (aCriterios[4] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Claves != null)
.Where(p => p.Claves.Replace("/", "__").ToLower().Contains(aCriterios[4].ToLower()));
}
var propietariosList = propietariosQuery.Skip((pageNumberP - 1) * pageSizeP).Take(pageSizeP)
.ToList();
var datosPropietarios = new
{
pageSize = pageSizeP,
pageNumber = pageNumberP,
recordsNumber = propietariosQuery.Count()
titulares = propietariosList
};
return Ok(datosPropietarios);
It works, but it's too slow (it takes several minutes). I've managed to make the initial query (the first page, unfiltered) fast by making recordsNumber = context.Propietarios.Count() but that breaks the pagination when filtering. And anyway, if I filter or if I go to a page near the end, it is again really slow.
How can I make the query faster?
My guess is that the query is pretty much traversing all the tables, so I don't know if there's even a solution that doesn't involve changing the data model.
It's because you are calling AsEnumerable, you are fetching all the data from Propietarios table to memory and the rest of operations you do after you call that method are executed using Linq to Objects instead of Linq to Entities, so your query is not translated to sql. Try removing it
Take a look of this post in case you need more info how AsEnumerable works with EF

How to use and display PagedResultDto

Using ASPNet Boilerplate, and returning a pagedResultSetDto with the below code, how do I display the page links?
public PagedResultDto<ArticleDto> GetAll()
{
var articleCount = articleRepository.Count();
var t = articleRepository.GetAllIncluding(x => x.articleImage).Include(x => x.Category).Where(
x => x.PublishFrom <= DateTime.Now &&
x.PublishTo >= DateTime.Now &&
x.Status == PostStatus.Published &&
x.IsDeleted == false
).OrderByDescending(x=> x.PublishFrom).ToList();
return new PagedResultDto<ArticleDto>
{
TotalCount = articleCount,
Items = t.MapTo<List<ArticleDto>>()
};
}
First, take in IPagedResultRequest as input:
// using Abp.Linq.Extensions;
public PagedResultDto<ArticleDto> GetAll(PagedResultRequestDto input)
{
var articleCount = articleRepository.Count();
var t = articleRepository
.GetAllIncluding(x => x.articleImage)
.Include(x => x.Category)
.Where(x =>
x.PublishFrom <= DateTime.Now &&
x.PublishTo >= DateTime.Now &&
x.Status == PostStatus.Published &&
x.IsDeleted == false
)
.OrderByDescending(x => x.PublishFrom)
.PageBy(input) // Page by SkipCount and MaxResultCount
.ToList();
return new PagedResultDto<ArticleDto>
{
TotalCount = articleCount,
Items = t.MapTo<List<ArticleDto>>()
};
}
Then create your own links to pass in SkipCount, e.g. GetAll?SkipCount=10 for page 2.
MaxResultCount has a default value of 10.
You can calculate it according to the result of GetAll().
You request how many records you want. Let's say 10 (default value).
It returns TotalCount and Items (=records). Let's say TotalCount = 95. Divide 95/10 = 9.5 ~=> 10 pages. Show 10 links. While 9 pages will show 10 records, last page will have 5 records. That

LINQ select item from a list where string contains any of the search terms in a list -> refactor

I have list of Items, called Translations. I filter the translations based on a search term from a search box, currently it looks like this:
private static IList<Translation> FilterTranslationListOLD(string filter, IEnumerable<Translation> translationList)
{
filter = filter.ToLower();
if (!string.IsNullOrEmpty(filter))
{
return translationList
.Where(t => (t.Tag.Filename.ToLower().Contains(filter)
|| t.Tag.FilePath.ToLower().Contains(filter)
|| t.Tag.TagContent.ToLower().Contains(filter)
|| (t.Tag.SanitizedTagContent != null && t.Tag.SanitizedTagContent.ToLower().Contains(filter))
|| (t.TagTranslation != null && t.TagTranslation.ToLower().Contains(filter))
|| (t.SanitizedTranslation != null && t.SanitizedTranslation.ToLower().Contains(filter))))
.OrderBy(t => t.Tag.FilePath)
.ThenBy(t => t.Tag.Filename).ThenBy(t => t.Tag.Id).ToList();
}
return translationList.OrderByDescending(t => t.DateTranslated).ToList();
}
I've now introduced the ability to search with multiple keywords, like so:
private static IList<Translation> FilterTranslationList(string filter, IEnumerable<Translation> translationList)
{
filter = filter.ToLower();
var splitFilterTerms = filter.Split(',');
if (splitFilterTerms.Any(split=>!string.IsNullOrEmpty(split)))
{
var translationListResults = new List<Translation>();
foreach (var splitFilterTerm in splitFilterTerms)
{
translationListResults.AddRange(translationList
.Where(t => (t.Tag.Filename.ToLower().Contains(splitFilterTerm)
|| t.Tag.FilePath.ToLower().Contains(splitFilterTerm)
|| t.Tag.TagContent.ToLower().Contains(splitFilterTerm)
|| (t.Tag.SanitizedTagContent != null && t.Tag.SanitizedTagContent.ToLower().Contains(splitFilterTerm))
|| (t.TagTranslation != null && t.TagTranslation.ToLower().Contains(splitFilterTerm))
|| (t.SanitizedTranslation != null && t.SanitizedTranslation.ToLower().Contains(splitFilterTerm))))
.OrderBy(t => t.Tag.FilePath)
.ThenBy(t => t.Tag.Filename).ThenBy(t => t.Tag.Id).ToList());
}
return translationListResults;
}
return translationList.OrderByDescending(t => t.DateTranslated).ToList();
}
what I would like to know is, is there a nicer way of writing this? Whilst it works, it would be nice to know how to do it in all linq or reduce/refactor it a little (make it a little neater). Thanks in advance!
Try looking at SelectMany, which will help you flatten a sequence of sequences:
private static IList<Translation> FilterTranslationListOLD(string filter, IEnumerable<Translation> translationList)
{
filter = filter.ToLower();
var splitFilterTerms = filter.Split(',');
if (splitFilterTerms.Any(split=>!string.IsNullOrEmpty(split)))
{
return splitFilterTerms.SelectMany(f => translationList
.Where(t => (t.Tag.Filename.ToLower().Contains(f)
|| t.Tag.FilePath.ToLower().Contains(f)
|| t.Tag.TagContent.ToLower().Contains(f)
|| (t.Tag.SanitizedTagContent != null && t.Tag.SanitizedTagContent.ToLower().Contains(f))
|| (t.TagTranslation != null && t.TagTranslation.ToLower().Contains(f))
|| (t.SanitizedTranslation != null && t.SanitizedTranslation.ToLower().Contains(f))))
.OrderBy(t => t.Tag.FilePath)
.ThenBy(t => t.Tag.Filename).ThenBy(t => t.Tag.Id)).ToList();
}
return translationList.OrderByDescending(t => t.DateTranslated).ToList();
}
I haven't actually run this code. Here is the MSDN documentation of SelectMany.
The problem with the above code is that it displays in OR condition and not AND...
So if you have these items:
List<Car> Cars = new List<Car>();
Cars.Add(new Car(){Manufacturer="Mercedes Benz", Color="Blue"});
Cars.Add(new Car(){Manufacturer="Mercedes Benz", Color="Green"});
it will display both if the filter is "Mercedes Blue"
I used this code to show only the blue car:
string Filter = "Mercedes blue";
List<string> SplittedFilter = new List<string>(Filter.ToLowerInvariant().Split(' '));
List<Car> FilteredCars = Cars;
foreach (var item in SplittedFilter) {
FilteredCars = (from c in FilteredCars
where c.Manufacturer.ToLowerInvariant().Contains(item) || c.Color.ToLowerInvariant().Contains(item)
select c).ToList();
}
Source: http://www.groggyjava.tv/blog/?p=84

Resources