How can I get my orderby to work using an anonymous type? - linq

What do I put in my order by?? I want to order by Name. I have moved the orderby after the distinct because I read that it needs to be done last.
var result = (from r in db.RecordDocs
where r.RecordID == recordID
select new
{
DocTypeID = r.Document.DocType.DocTypeID,
Name = r.Document.DocType.Name,
Number = r.Document.DocType.Number
}
).Distinct().OrderBy( );

Just do
.OrderBy(doc => doc.Name)

Another option, if you really prefer the query expression syntax would be to chain your query construction across multiple statements:
var query = from r in db.RecordDocs
where r.RecordID == recordID
select new
{
DocTypeID = r.Document.DocType.DocTypeID,
Name = r.Document.DocType.Name,
Number = r.Document.DocType.Number
};
query = query.Disctinct();
query = from doc in query orderby doc.Name select doc;
Since all of these methods are deferred, this will result in the exact same execution performance.

Related

Passing different values to the SELECT NEW part of a LINQ query

I am creating a result object from my query, something like this:
var result = from m in MyTable
join r in some_more_tables
select new ResultSummmary
{
Description = m.Description,
start_date = r.start_dat
};
But based on some condition before I get to this query and SELECT NEW, I want to be able to flex what I put in its Description filed, currently it is always m.Description but sometimes I want it to be a static text like "Hospital" and the rest of the times I want it to be m.Description as it is now.
How can we write it that way to be flexible?
Let's pretend the condition is stored in a variable called condition. This would allow you to write the following
var result = from m in MyTable
join r in some_more_tables
select new ResultSummmary
{
Description = condition ? m.Description : "Hospital",
start_date = r.start_dat
};
select new ResultSummmary
{
Description = someBool ? m.Description : "Hospital",
start_date = r.start_dat
};

need to return the first record linq

I need to return only the first record. Although I had to put the z.FirstOrDefault(); still more than one were displayed
public DataTable GetDependents(string EmployeeID)
{
HealthCareSystem.DataClassesDataContext db = new HealthCareSystem.DataClassesDataContext();
var z = (from s in db.SelectingDependentsGroupBies
where s.EmployeeID.Equals(EmployeeID)
join d in db.Dependents on s.DependentID equals d.DependentID
orderby s.DependentID descending
//Selecting wanted tables dependents fields by datatable
select new DependentsX { DependentID = Convert.ToInt32(s.DependentID), EmployeeID = s.EmployeeID, Name = s.Name, Surname = s.Surname, IDCardNo = s.IDCardNo, ContactNo = s.ContactNo, BirthDate = s.BirthDate, StartSchemeDate = s.StartDate, EndSchemeDate = s.EndDate, RelationType = s.Type, Payment = Convert.ToDouble(d.Payment), });
var firstRecord = z.FirstOrDefault();
Add this line after your existing code:
var firstRecord = x.First();
If there might be zero results and you don't want an exception then you can use FirstOrDefault instead.
var firstRecord = x.FirstOrDefault();
Another common way is to enclose your query in parenthesis and then include the extension methods outside the parenthesis:
var x = (from d in db.DependentsRelationsViews
where d.IDCardNo.Equals(DepID)
orderby d.DependentID descending
select new DependentsX
{
DependentID = Convert.ToInt32(d.DependentID),
EmployeeID = d.EmployeeID,
Name = d.Name,
Surname = d.Surname,
IDCardNo = d.IDCardNo,
ContactNo = d.ContactNo,
BirthDate = d.BirthDate,
StartSchemeDate = Convert.ToDateTime(d.StartSchemeDate),
EndSchemeDate = d.EndSchemeDate,
Payment = d.Payment,
RelationType = Convert.ToString(d.Type)
}).FirstOrDefault();
If you don't enclose it in parenthesis and try to call FirstOrDefault() then you're applying that extension to the anonymous type in just the very last Select clause. By enclosing the whole query in parenthesis and then calling the FirstOrDefault() extension, you're indicating to the compiler that you wish to apply it to the return value of your entire query, which will be the IEnumerable<> or IQueryable<> collection.

How can I define a List to add results of a query in a loop?

I have an array filled with long type values and for each value in the array I need to implement a query. I used foreach loop as you can see from the code below:
var result;
foreach(long id in PrdIdArr)
{
var mainQuery = (from o in db.OPERATIONs
join u in db.UNITs on o.OP_UNIT_ID equals u.UNIT_ID into smt
from s in smt
join x in db.XIDs on s.UNIT_ID equals x.UNIT_ID
where o.OP_OT_CODE == OtCode
where x.IDTYP_CD == "BSN"
where s.START_PRD_ID == id
where o.OP_UPD_DATE >= _StartDate
where o.OP_UPD_DATE <= _EndDate
select new
{
o.OP_ID,
o.OP_UPD_DATE,
x.EXTERNAL_ID,
o.OP_OS_CODE,
o.OP_START,
o.OP_ST_STATION,
s.START_PRD_ID
}).Take(_RowNumber);
//var result = mainQuery.ToList();
result.add(mainQuery.ToList());
}
data = this.Json(result);
data.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return data;
However, I have a problem in my code; I have to define a main list just before the foreach loop so that I could add results of each query to the that main list. my question is: How can I define this list as you can see at the beginning of my code? Thanks for the help...
How can I define this list as you can see at the beginning of my code?
Make
new {
o.OP_ID,
o.OP_UPD_DATE,
x.EXTERNAL_ID,
o.OP_OS_CODE,
o.OP_START,
o.OP_ST_STATION,
s.START_PRD_ID
}
into a concrete type (say QueryResult, although something a little more specific than that), and then just declare
var result = new List<QueryResult>();
Also, you should consider turning
foreach(long id in PrdIdArr)
and
where s.START_PRD_ID == id
into
where PrdIdArr.Contains(s.Start_PRD_ID)
var result = new List<object>();
foreach(long id in PrdIdArr)
{
....
result.Add(mainQuery.ToList());
}
You could do this:
var result = PrdIdArr.Select(id =>
from o in db.OPERATIONs
join u in db.UNITs on o.OP_UNIT_ID equals u.UNIT_ID into smt
from s in smt
join x in db.XIDs on s.UNIT_ID equals x.UNIT_ID
where o.OP_OT_CODE == OtCode
where x.IDTYP_CD == "BSN"
where s.START_PRD_ID == id
where o.OP_UPD_DATE >= _StartDate
where o.OP_UPD_DATE <= _EndDate
select new
{
o.OP_ID,
o.OP_UPD_DATE,
x.EXTERNAL_ID,
o.OP_OS_CODE,
o.OP_START,
o.OP_ST_STATION,
s.START_PRD_ID
}
.Take(_RowNumber)
.ToList()
).ToList();
I highly recommend performing some Extract Method refactorings, as the code is pretty complex and hard to understand/mange this way.
Just create the anonymous type outside with the same property names and the correct type
var result = Enumerable.Range(0, 0).Select(x => new
{
OP_ID = 1,
OP_UPD_DATE = DateTime.Now,
EXTERNAL_ID = 1,
OP_OS_CODE = 1,
OP_START = DateTIme.Now,
OP_ST_STATION = "",
START_PRD_ID = 1,
}).ToList();
And in your loop call AddRange
result.AddRange(mainQuery.ToList());

Linq - How to query specific columns and return a lists

I am trying to write a linq query that will only return certain columns from my entity object into a list object.
Below is my code which produces an error(can't implicitly convert a generic list of anonymous types to a generic list of type TBLPROMOTION):
IQueryable<TBLPROMOTION> matches = webStoreContext.TBLPROMOTION.Include("TBLSTORE").Include("LKPROMOTIONTYPE");
List<TBLPROMOTION> promotionInfo = null;
promotionInfo = (from p in matches
orderby p.PROMOTION_NM descending
select new { p.EFFECTIVE_DT, p.EXPIRE_DT, p.IS_ACTIVE,
p.PROMOTION_DESC, p.PROMOTION_ID, p.PROMOTION_NM }).ToList();
What would be the best way to accomplish this. I do not want to do a "select p" in this case and return all the columns associated with the query.
thanks in advance,
Billy
Can't you do var promotionInfo = () and get a list of anonymous types?
Okay, basically you can not cast an Anonymous type to a known type like TBLPROMOTION.
ofcourse, you can say var promotionInfo = and then get an IEnumerable<{Anonymoustype}> and use that to do, what you were wanting to do with promotionInfo.
Also, personally I prefer the Fluent version of a linq query, easy on the eyes, good programming diet, at least for me :)
var promotionInfo = matches
.OrderByDescending( p => p.PROMOTION_NM)
.Select( p => new { p.EFFECTIVE_DT,
p.EXPIRE_DT,
p.IS_ACTIVE,
p.PROMOTION_DESC,
p.PROMOTION_ID,
p.PROMOTION_NM})
.ToList();
If you're moving from a L2E query to a Type already defined, you may need a step between. I haven't tried to compile this but something like:
List<TBLPROMOTION> promotions = new List<TBLPROMOTION>();
var results = from p in matches
orderby p.PROMOTION_NM descending
select new
{
p.EFFECTIVE_DT,
p.EXPIRE_DT,
p.IS_ACTIVE,
p.PROMOTION_DESC,
p.PROMOTION_ID,
p.PROMOTION_NM
};
foreach (var v in results)
{
promotions.Add(new TBLPROMOTION(v.EFFECTIVE_DT, v.EXPIRE_DT, v.IS_ACTIVE,
v.PROMOTION_DESC, v.PROMOTION_ID, v.PROMOTION_NM));
}
Based on the comment below, you might try something like:
foreach(var v in results)
{
TBLPROMOTION temp = new TBLPROMOTION();
temp.EFFECTIVE_DT = v.EFFECTIVE_DT;
temp.EXPIRE_DT = v.EXPIRE_DT;
temp.IS_ACTIVE = v.IS_ACTIVE
// Assign Other Properties
promotions.Add(temp);
}
.......
Sorry: Just read the addition to the top.
Are you sure that none of the fields you're leaving out (instead of saying "select p") are required for a TBLPROMOTION object? Also, sense your TBLPROMOTION object is going to have properties (and therefore memory allocated) for those skipped fields, why not just use an annonymous type or set up a helper class that contains only your needed properties?
#Billy, following code worked for me.
List<TBLPROMOTION> promotionInfo =
(from p in matches
orderby p.PROMOTION_NM descending
select new TBLPROMOTION(p.EFFECTIVE_DT, p.EXPIRE_DT, p.IS_ACTIVE,
p.PROMOTION_DESC, p.PROMOTION_ID, p.PROMOTION_NM)
).ToList();
did you try
select new TBLPROMOTION {.....
instead of
select new {.....
List<TBLPROMOTION> promotionInfo = null;
promotionInfo = (from p in matches
orderby p.PROMOTION_NM descending
select new TBLPROMOTION { COL1 = p.EFFECTIVE_DT, COL2 = p.EXPIRE_DT, COL3 = p.IS_ACTIVE... }).ToList();
Where COL1, COL2, ... are the names of the properties on TBLPROMOTION you wish you populate.
If you want a subset of the table you have 2 options:
#Fredou mentioned select new TBLPROMOTION{...}
other way is to create a custom DTO which has the exact properties & select them instead like:
List promotionInfo = ...
select new TBLPROMOTION_DTO{
Effective_dt = ...
}
HTH

Iterating Linq result set using indexers

Let's ay I have this query:
var results = from row in db.Table select row;
How can I access this:
string name = results[0]["columnName"];
if you really want a particular index you can use the Skip() method with First().
var rowOffset = 0;
var results = (from row in db.Table
select row).Skip(rowOffset).First()["columnName"];
But unless you are using a Where clause I would really recommend using the indexer. The indexer is pretty much a direct reference while the LINQ statement would be using the objects iterator.
Also don't forget you can do much more advanced stuff with LINQ.
var rowOffset = 0;
var pageLength = 10;
var results = (from row in db.Table
let colValue = row["columnname"]
where colValue != null
select colValue.ToString()
).Skip(rowOffset)
.Take(pageLength)
.ToArray();
var commaString = string.Join(", ", results);
If you specifically just want the zeroth element, you can use results.First()
results is a IEnumerable list of Rows. So you can get it with a simple foreach.
foreach(var row in results)
{
string name = row["columnName"];
}
(from row in db.Table select row).First().columnName

Resources