At least one object must implement IComparable? - asp.net-mvc

Model:
return (from m in meterReadings
group m by new { date = m.ReadDate } into g
select new
{
ReadDate = g.Key.date.ToString("dd.MM.yyyy - HH:mm:ss"),
T1 = from t1 in g
where t1.Name == "T1"
select t1.Value.ToString("0,0.000"),
T2 = from t2 in g
where t2.Name == "T2"
select t2.Value.ToString("0,0.000"),
T3 = from t3 in g
where t3.Name == "T3"
select t3.Value.ToString("0,0.000"),
Total = from total in g
where total.Name == "Toplam"
select total.Value.ToString("0,0.000")
}).AsQueryable<object>();
Query
var table = MeterReadingManager.GetMeterReadingsPivot(meterReadings, 1);
//No Error (in title)
rows = table.OrderBy("ReadDate","desc").Skip((pageIndex) * pageSize).Take(pageSize)
//Error (in title)
rows = table.OrderBy("T1","desc").Skip((pageIndex) * pageSize).Take(pageSize)
When I order by ReadDate, It works. But When I try to order by other fields I get the error : At least one object must implement IComparable
Why I get this error? And How can I fix it?

If you want to sort a list of items of any type, the type must implement IComparable for the sort algorithm to be able to compare items. T1 is an IQueryable, whcih does not implement IComparable. I think you intended to create string values for T1, T2, and T3. If so, you should add FirstOrDefault() to each linq statement creating T1, etc.
Edit
(After your comment)
I mean this:
T1 = (from t1 in g
where t1.Name == "T1"
select t1.Value.ToString("0,0.000")).FirstOrDefault()
Now T1 is a string and, thus, it can be used in sorting.

You could try ThenByDescending:
var rows = table
.OrderByDescending(x => x.ReadDate).Skip((pageIndex) * pageSize).Take(pageSize)
.ThenByDescending(x => x.T1).Skip((pageIndex) * pageSize).Take(pageSize);
UPDATE:
You could use Reflection (a bit slower) if ordering by one field:
var tableInfo = table.GetType().GetProperty("T1");
var sortedRow = table.OrderByDescending(x => tableInfo.GetValue(x, null)).Skip((pageIndex) * pageSize).Take(pageSize);

Related

I can not upload data to a VirtualStringTree

I have a form with a TPageControl that has two tabs. In each of them there is a TVirtualStringTree and I have defined these two structures:
typedef struct tagTTreeMun
{
AnsiString Municipio;
int Padron;
int Censo;
double Relacion;
int Codigo;
} TTreeMun, *PTreeMun;
typedef struct tagTTreePro
{
AnsiString Proceso;
int Padron;
int Censo;
double Relacion;
int Codigo;
}TTreePro, *PTreePro;
I know: they are almost the same; then I explain it. The first one is loaded from four nested querys and it does it without any problem, but the second one ... There's no way!
To load this second I need two querys:
SELECT DISTINCT Date FROM Elections ORDER BY Date DESC
that field Date contains only the year and runs without any problem.
SELECT A.Codigo, B.Name, SUM (C.Padron) Padron, SUM (C.Censo) Census, A.Closed
FROM Elections A, Process B, HisElec C
WHERE A.CodPrv = (SELECT Literal FROM Installation WHERE Label = 'Province')
AND A.CodPrv = B.CodPrv AND B.Codigo = A.Process AND A.Closed = 1
AND A.CodPrv = C.CodPrv AND A.Codigo = C.Election
AND A. Date =: Date
GROUP BY 1, 2, 5
UNION
SELECT A.Codigo, B.Name, SUM (C.Padron) Padron,
(SELECT SUM (Census) FROM Tables WHERE CodPrv = (SELECT Literal FROM Installation WHERE Label = 'Province')) Census,
A.Closed
FROM Elections A, Process B, Dl01 C
WHERE A.CodPrv = (SELECT Literal FROM Installation WHERE Label = 'Province')
AND A.CodPrv = B.CodPrv AND A.Process = B.Code AND A.Closed = 0
AND A. Date =: Date
GROUP BY 1, 2, 5
ORDER BY 1 DESC, 3
It also runs without problems or errors. The problem comes when trying to pass that data to the corresponding TVirtualStringTree.
PTreePro DatPro;
PVirtualNode Node1, Node2, Node3, Node4;
LisPro->NodeDataSize = sizeof (TTreePro);
LisPro->BeginUpdate ();
LisPro->Clear ();
for (;! qTemp1->Eof; qTemp1->Next ())
{
Node1 = LisPro->AddChild (NULL);
DatPro = (PTreePro) LisPro->GetNodeData (Node1);
DatPro->Process = IntToStr(qTemp1->FieldByName ("Date")->AsInteger);
qTemp2->Close ();
qTemp2->ParamByName ("Date")->AsInteger = qTemp1->FieldByName("Date")->AsInteger;
qTemp2->Open ();
for (;! qTemp1->Eof; qTemp1->Next())
{
Node2 = LisPro->AddChild(Node1);
DatPro = (PTreePro)LisPro->GetNodeData(Node2);
DatPro->Process = qTemp1->FieldByName("Name")
[...]
}
}
When trying to create that Node1 in this query, the lines Node1 = ... and DatPro = (PTreePro) ... are executed without major problem, except that Node1, after running the AddChild, has a NULL value and therefore, from then on, it can only give an error because when trying to give value to Process, it automatically gives an execution error.
I have tried putting the load of each of the trees in a different function, by isolating code; I have tried with the same structure (in the end they are identical) or as in the example with two structures, to change the order of execution. For more tests that I have done I am not able to load both trees, in LisPro I ALWAYS do the same to me.

Failing to query from database

I'm trying to get a count of occurrences of a value from my database. It's failing.
My effort is
var dc = new Dal.Entities();
var query = (from d in dc.Instruments
where d.Src.ToLower().Contains("other.png")
select new
{
count = d.Src.Count(),
key = d.Src
}
);
This keeps throwing the following exception
"DbExpressionBinding requires an input expression with a collection ResultType.\r\nParameter name: input"
If I change select new... to select d then it works fine so I know that part of the query is OK.
I don't understand why I can't get a Count of each string it finds. What did I do wrong?
edit
If my database is
Src (column title)
my value
my other value
my value
I'm hoping to get the result of
my value, 2
my other value, 1
You need to group by then:
var query = from d in dc.Instruments
where d.Src.ToLower().Contains("other.png")
group d by d.Src into g
select new
{
count = g.Count(),
key = g.Key
};
var items = dc.Instruments
.Where(p => p.Src.ToLower().Contains("other.png"))
.Count();
or
var items = (from item in dc.Instruments
where item.Src.ToLower().Contains("other.png")
select item).Count();

How do you use the Group Statement on your SQL to Linq queries?

I would like to end up with a list where my categories are grouped according to the users id.
IEnumerable<JoinClass> catList =
from c in db.Users2
join e in db.Categories on c.Id_Users equals e.FK_Users
where c.EEID == UserEEID
group e.Category by c.EEID in z
select new JoinClass
{
Category = e.Category,
EEID = c.EEID,
};
return View(catList.ToList() );
IEnumerable<JoinClass> catList =
from c in db.Users2
join e in db.Categories on c.Id_Users equals e.FK_Users
where c.EEID == UserEEID
group e.Category by c.EEID in z
select new JoinClass
{
Categories = z.ToList(),
EEID = z.Key,
};
return View(catList.ToList() );
Assuming you ACTUALLY meant to find all Categories for each EEID.

Search ranking in LINQ, MVC 3 and Entity Framework

Previously in SQL I would use something like this to rank my search results:
--search product name
SELECT tblProduct.ProductID, 20 AS Ranking
FROM tblProduct
INNER JOIN tblManufacturer ON tblProduct.ManufacturerID=tblManufacturer.ManufacturerID
LEFT OUTER JOIN tblProductCollection ON tblProduct.CollectionID=tblProductCollection.CollectionID
WHERE tblManufacturer.Name + ISNULL(' ' + tblProductCollection.CollectionName, '') + ' ' + tblProduct.Name LIKE '%' + #term + '%' AND tblProduct.Active = 1
UNION ALL
--search product exact name
SELECT tblProduct.ProductID, 200 AS Ranking
FROM tblProduct WHERE Name = '%' + term AND tblProduct.Active = 1
UNION ALL
This example says if your search term is contained in the name: 20 is the rank, if you match the name exactly: 200 is the rank. Union the tables together, order by Ranking(descending) and hey presto!
I'm trying to do this in LINQ this time round and am unsure how to go about doing it, to be honest I'm unsure my previous example was the best way to do it originally.
So, I have a Product Entity mapped to my database and I've added a property in my partial class called SearchRanking:
var query = from p in db.Products
where p.Name.Contains(term)
select p;
var query2 = from p in db.Products
where p.Name.ToLower() == term
select p;
Somehow I need to set the properties like so:
var query = from p in db.Products
where p.Name.Contains(term)
select p, p.SearchRanking = 20;
var query2 = from p in db.Products
where p.Name.ToLower() == term
select p, p.SearchRanking = 200;
Am I on the right track?
If you're wanting to create a new anonymous type you could do this:
var foundProducts = (from p in products
where p.Name.Contains(term)
select new Product
{
ProductId = p.ProductId,
Category = p.Category,
Brand = p.Brand,
SearchRanking = p.Name.ToLower() == term ? 200 : 20
}).OrderBy(s => s.SearchRanking).Take(20);
I would do something like this;
var query = (from p in db.Products
where p.Name.Contains(term)
select p).ToList().ForEach(p => p.SearchRanking = 20);
A more efficient way would be to;
var query = (from p in db.Products
where p.Name.Contains(term)
select new Product
{
Id = p.Id,
//set the other props here
SearchRanking = 20
}).ToList();

Nested query in Linq

I have three tables. I have to retrieve the data using Linq statement. My three table names are A,B,C. I connected join for connecting two tables A and B based on the id's like:
select ol, fN, LN, ci, co
from member
join details
on member_id = details_id
where details_id in
(select contacts_id from contacts where
contacts_id1 = 1 and contacts_usr_id = 1)
I am able to write the query up to the where condition, how can I write the query for the inner while condition?
you can try this:
var idlist = (from tbl in table3
where tbl.usr_id == 1 && tbl.contacts_id == 1
select tbl.contacts_id ).ToList();
var x = from A in table1
from B in table2 where A.user_id == B.user_id
&& idlist.Contains(A.user_id)
select new { a = A.a, b = A.b, c = A.c, d = B.d, e = B.e };
check and let me know if that work.
Try flipping the query upside down. How about the following:
var query =
from t3 in table3
where t3.user_id = 1 && t3.contacts_id = 1
join t2 in table2 on t3.contacts_id equals t2.usr_id
join t1 in table1 on t2.usr_id equals t1.userid
select new {t2.a, t2.b, t2.c, t1.d, t1.e};

Resources