Ordering int values orders 11,12,13 before 2 - c#

In my Sql table the index primary key is an integer (1,2,3,...)
I have an Entity query like this :
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.OrderByDescending(qa => qa.Code)
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
And the result sorted list is like this:
1
11
12
...
2
21
22
...
3
31
32
...
What should be right to show correct ordered numbers?
Edit>>>
Table in sql :
Table in sql
The project is Model First Not Code First
The model :
public class QAViewModels
{
public int Code { get; set; }
public string Question { get; set; }
public string InquirerName { get; set; }
public string InquirerEmail { get; set; }
public int VisitCounts { get; set; }
public Nullable<int> Respondent { get; set; }
public Nullable<System.DateTime> RespondDate { get; set; }
public string Answer { get; set; }
public string AnswerSummary { get; set; }
public virtual BaseMember BaseMember { get; set; }
public static QAViewModels Set(QuestionAnswer qa)
{
return new QAViewModels
{
Code = qa.Code,
Question = qa.Question,
InquirerName = qa.InquirerName,
InquirerEmail = qa.InquirerEmail,
VisitCounts = qa.VisitCounts,
Respondent = qa.Respondent,
RespondDate = qa.RespondDate,
Answer = qa.Answer,
AnswerSummary = qa.AnswerSummary,
BaseMember = qa.BaseMember
};
}
}
All types are based on SQL table fileds data type
The Store :
public List<QAViewModels> GetAllRawPaged(int page, int pageSize, out int count)
{
var getAllQAs = Tools.DataModel.QuestionAnswers;
count = getAllQAs.Count();
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.OrderByDescending(qa => qa.Code)
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
return pagedQAs;
}
Actions and queries on data stored in QAStore
The Controller :
public ActionResult CM_QAs()
{
QAStore qas = new QAStore();
int count = 0;
LabelStore ls = new LabelStore();
List<TagsViewsModel> tags = ls.GetAllTags();
List<QAViewModels> allQAs = qas.GetAllRawPaged(1, 100, out count);
return View(allQAs);
}
Get all QuestionAnswers and pass to view
The View :
#model List<wrrc.Models.QAViewModels>
<div>
#foreach (var qa in Model)
{
<div>
<span>
<span>Question Number
#Tools.ConvertNumerals(Convert.ToString(qa.Code))
</span>
</span>
<div>#Html.Raw(qa.Question)</div>
<div>#Tools.TruncateAtWord(qa.Answer, 500)))</div>
<a href="#Url.Action("SingleQA", "QA" >Full Description</a>
</div>
}
</div>

You should sort the Code as int;
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.ToList()
.OrderByDescending(qa => int.Parse(qa.Code))
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
Also, It could be better to prevent possible null values or incorrect strings to parse integer;
int val = 0;
var pagedQAs = getAllQAs
.Where(qa => qa.Show)
.ToList()
.OrderByDescending(qa => int.TryParse(qa.Code,out val) ? val : Int32.MaxValue)
.Skip((page - 1) * pageSize).Take(pageSize)
.Select(QAViewModels.Set)
.ToList();
Also, with this query you should perform order/skip/take actions on the client side. int.TryParse or int.Parse can't be translated to sql query in IQueryable form. So, if you have a chance to modify Code column as int in the database, it could be better solution.

Related

Groupby in c# to Add in new list

I have a filtered data according to date and group it according to document type and count it like:
Data1 - Memo
Data2 - Lett
Data3 - Memo
Data4 - Case
Output
Memo - 2
Lett - 1
Case - 1
I don't know if I'm doing it right. I can't display the output to View
Model--
public class ViewModelIndexTransfiles
{
public int Count { get; set; }
public string idoctype { get; set; }
public List<TransFile> transPrint { get; set; }
public List<TransFile> summary { get; set; }
}
Controller--
modelPrint.transPrint = db.TransFiles.Where(s => (s.tfl_idetype == selectedtrstyp) &&
(DbFunctions.TruncateTime(s.tfl_update) >= modelPrint.dteFrom.Date &&
DbFunctions.TruncateTime(s.tfl_update) <= modelPrint.dteTo.Date)).ToList();
//This one is good as I was able to filter the data first according to date and display the data using modelPrint.transPrint
var doccount = modelPrint.transPrint.GroupBy(o => o.tfl_idoctype).Select(x =>
new { tfl_idoctype = x.Key, Count = x.Count() }).ToList();
// this one is the grouped data. I don't know what is next to this so I can display the desired output or pass it to view.
return View(modelPrint);
// I don't know which is to return :(
View--
#foreach (var member in Model.summary)
{
<tr>
<td>Document Type</td>
<td>Count</td>
</tr>
}
I tried this code before the return, but It's not working.
for (int i = 0; i < doccount.ToList().Count; i++)
{
modelPrint.summary.Add(
new ViewModelIndexTransfiles
{
idoctype = doccount[i].tfl_idoctype,
Count = doccount[i].Count
});
What am I missing?

Is it possible to index the properties of a collection in LiteDb

I have a result object in litedb with a collection property, as below:
public class Result
{
public int Id { get; set; }
public ICollection<Entity> ExtractedEntities { get; set; }
}
public class Entity
{
public string Value { get; set; }
public int Id { get; set; }
}
Is it possible to index the properties of the entity class so that I can do something like:
collection.Find(r => r.ExtractedEntities.Any(ee => ee.Value == "test" && ee.Id == 1));
Thanks
Yes.
using(var db = new LiteDatabase(#"C:\Temp\MyData.db"))
{
var col = db.GetCollection<Customer>("customers");
// Index document using document Name property
col.EnsureIndex(x => x.Name);
// Use LINQ to query documents
var results = col.Find(x => x.Name.StartsWith("Jo"));
// Let's create an index in phone numbers (using expression). It's a multikey index
col.EnsureIndex(x => x.Phones, "$.Phones[*]");
// and now we can query phones
var r = col.FindOne(x => x.Phones.Contains("8888-5555"));
}
You find this in the documentation here or here

Sending select parameters outside of a function?

I'am trying to send two select paramaters to a function from outside. What i am trying to achieve is simplified at below
I have a model like this,
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
SampleData:
3 / Barrack / Obama
4 / Vladimir / Putin
and an another model
public class IdTextModel
{
public string Id { get; set; }
public string Text { get; set; }
}
and I'm trying to create a function like this
public List<IdNameModel> GetList(propselectorA, propselectorB){
return data.Select(x => new IdTextModel(){
Id = propselectorA,
Text = propselectorB
});
}
Usage:
var list = GetList(x => x.Id, x => x.Surname);
ExpectedResult:
3 / Obama
4 / Putin
How can i accomplish that? Thank you.
You can use Expression<Func<Entity,IdNameModel>> to abstract out the types of Id and Text:
public List<T> GetList(
Expression<Func<Entity,T>> selector
) {
return data.Select(selector).ToList();
}
and call it like this:
var list = GetList(x => IdTextModel { Id = x.Id, Name = x.Surname } );
Passing selectors for two string properties is also possible, but using Zip makes it less efficient:
public List<IdTextModel> GetList(
Expression<Func<Entity,string>> selectorId
, Expression<Func<Entity,string>> selectorName
) {
return data
.Select(selectorId)
.Zip(
data.Select(selectorName)
, (id, name) => new IdTextModel { Id = id, Name = name }
).ToList();
}

Linq "join" with a IList<T> getting "Error Unable to create a constant value.."

I have a Save Method that saves with a Linq query a manually re-orderd list (in a web form) that is passed as the parameter to my method, and I try to update the Order Property of the IEnumerable<VM_CategoryLabel> I retrieve from the database (EF) with the corresponding value in the list (maybe would that be clearer with my code below):
public static void SaveFromList(IList<VM_CategoryLabelExtra> listTemplate)
{
int idCat = listTemplate.Select(x => x.IdCat).FirstOrDefault();
var test = (int)listTemplate.Where(z => z.Id == 8).Select(z => z.Order).FirstOrDefault();
using (var context = new my_Entities())
{
var requete = from x in context.arc_CatLabel
where x.ID_Categorie == idCat
orderby x.Sequence_Cat
select new VM_CategoryLabel
{
Id = x.ID_LabelPerso,
//Order = x.Sequence_Cat,
Order = (int)listTemplate.Where(z => z.Id == x.ID_LabelPerso).Select(z => z.Order).First(),
Label = x.arc_Label.Label,
Unit = x.arc_Label.Unit
};
context.SaveChanges();
}
}
I used the "test" var to see if my "sub-query" gets the correct value, and it does, but when I use my Linq expression inside the Select (the commented Order line), I get the following error:
Unable to create a constant value of type 'Namespace.Models.VM_CategoryLabelExtra. "Only primitive types and enumeration types are supported in this context.
Here are my classes:
public class VM_CategoryLabel
{
public int Id { get; set; }
public int Order { get; set; }
public string Label { get; set; }
public string Unit { get; set; }
public bool Checked { get; set; }
}
public class VM_CategoryLabelExtra
{
public int Id { get; set; }
public int IdCat { get; set; }
public int Order { get; set; }
public string Label { get; set; }
public string Unit { get; set; }
public bool Checked { get; set; }
}
So I suppose that I should not query the list inside my query ? So how do I "match" the 2 lists of values ?
I also tried the following (after having replace in the Linq query: Order = x.Sequence_Cat)that is not working neither because the iteration variable is
read-only:
foreach (var item in requete)
{
item.Order = listTemplate.Where(x => x.Id == item.Id).Select(x => x.Order).FirstOrDefault();
}
try
{
context.SaveChanges();
I suggest using this.
It is the let clause.
public static void SaveFromList(IList<VM_CategoryLabelExtra> listTemplate)
{
int idCat = listTemplate.Select(x => x.IdCat).FirstOrDefault();
var test = (int)listTemplate.Where(z => z.Id == 8).Select(z => z.Order).FirstOrDefault();
using (var context = new my_Entities())
{
var requete = from x in context.arc_CatLabel
where x.ID_Categorie == idCat
orderby x.Sequence_Cat
let list = listTemplate
select new VM_CategoryLabel
{
Id = x.ID_LabelPerso,
Order = list.Where(z => z.Id == x.ID_LabelPerso).Select(z => z.Order).First(),
Label = x.arc_Label.Label,
Unit = x.arc_Label.Unit
};
context.SaveChanges();
}
}
edit: instead offrom you can just do let list = listTemplate
Should work now :)
example for let:
// The let keyword in query expressions comes in useful with subqueries: it lets
// you re-use the subquery in the projection:
from c in Customers
let highValuePurchases = c.Purchases.Where (p => p.Price > 1000)
where highValuePurchases.Any()
select new
{
c.Name,
highValuePurchases
}
If you do not know how Let working than please download LinqPad and see an example

20 most viewed "codes" with include "User" and "Language"

I have two tables "Codes" and "Views" and want to get a list of the 20 Codes with most views since x days ago (thats my variable dt).
Im able to get the list and sort it, but i have a problem i also would like to include 2 other tables "User" and "Language".
var query = from f in _db.Codes
select new
{
Code = f,
PostCount = f.ViewModels.Count(p => p.timestamp > dt)
};
var result = query.OrderByDescending(x => x.PostCount).Select(y => y.Code).Take(20)
But after doing like this i'm not able to Include my other tables. I tried to convert the result to a ObjectQuery but then it becomes null (there are 20 Codes in the result before trying to convert it).
The Code model looks like this
[Key]
public int CodeID { get; set; }
public int UserID { get; set; }
public UserModel User { get; set; }
[DisplayName("Language")]
public int LanguageID { get; set; }
public LanguageModel Language { get; set; }
public virtual ICollection<ViewModel> ViewModels { get; set; }
Easy solution:
IEnumerable<CodeModel> posts = _db.Codes
.Include("User")
.Include("Language")
.OrderByDescending(f => f.ViewModels.Count(p => p.timestamp > dt))
.Take(20);

Categories