Update class field in LINQ - is it possible? - linq

I have 2 tables, and want to get records from 1 table and to "update" one of its fields from another table, and to pass final list of "Payment" objects somewhere. I cannot use anonymouse type, i need to get the list of proper typed objects.
There was a long way.
Got data:
var paymentsToShow = from p in paymentsRepository.Payments
join r in recordTypeRepository.RecordType
on p.RecordType equals r.Reference into p_r
where p.Customer == CustomerRef
from r in p_r.DefaultIfEmpty()
select new
{
Payment = p,
RecordType = r
};
var objList = paymentsToShow.ToList();
Change required field (basically, Payment.RecordTypeName is empty):
foreach (var obj in objList)
{
obj.Payment.RecordTypeName = obj.RecordType.Name;
}
Got list with correct type:
var paymentsList = from o in objList
select o.Payment;
Is there any way to get code shorter, to make required field update in the query or something else? I dont know where to look for.
I cannot change database.

You could do it like this:
var paymentsToShow = (from p in paymentsRepository.Payments
join r in recordTypeRepository.RecordType
on p.RecordType equals r.Reference into p_r
where p.Customer == CustomerRef
from r in p_r.DefaultIfEmpty()
select new
{
Payment = p,
RecordType = r
}).Select(x =>
{
x.Payment.RecordTypeName = x.RecordType.Name;
return x.Payment;
});
This will result in an IEnumerable<Payment>, so no anonymous type used.

Related

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 to Sql Query - better solution (optimizing)

The following code works, but it's not a nice code. (low performance)
I have a dictionary with value and key.
First i go trough every webcodes who exist. Then i load all participants in a list (where webcode equals the actual webcode in the foreach). After that i add the data (parameter of the webcode and a count of participants to the dictionary).
Guid compID = Guid.Parse(wID);
ChartModel webcodes = new ChartModel();
webcodes.Title = "Webcodes Statistics";
webcodes.Data = new Dictionary<string, int>();
var webcodesData = db.t_Webcode;
foreach (var w in webcodesData)
{
var wData = db.t_Participant.Where(t => t.FK_Competition == compID && t.Webcode == w.Webcode);
if (wData.Count() != 0)
webcodes.Data.Add(w.Parameter, wData.Count());
}
ViewBag.Webcodes = webcodes;
TIA
You need something along these lines:
webcodes.Data = (from w in db.t_Webcode
join p in db.t_Participant on w.Webcode equals p.Webcode
where p.FK_Competition == compID
group w by w.Parameter into g
select new { g.Key, Count = g.Count() }).ToDictionary();
I can't test it but that is the type of query you need.
This will assume that you have relationships defined in your database and that your LINQ to SQL datacontext are aware of them. If not, you will need to join manually on t_Participants from tWebcode.
This should execute in 1 single SQL query, instead of 1 query per row in tWebcode.
var webcodesAndNoOfParticipants =
from webcode in db.tWebcode
// Define number of participants for this webcode
let numberOfParticipants = webcode.t_Participants.Count(participant => participant.FK_Competition == compID)
where numberOfParticipants > 0
select new {
WebcodeParameter = webcode.Parameter,
NoOfParticipants = numberOfParticipants
};
webcodes.Data = webcodesAndNoOfParticipants.ToDictionary(x => x.WebcodeParameter, x => x.NoOfParticipants);

LINQ to remove duplicated property

I have a LINQ statement like this:
var media = (from p in postService.GetMedia(postId)
select new
{
PostId = postId,
SynthId = p.SynthId
});
There are many(possibly thousands) of records returned with the same SynthId. I want to select one one, any random one. So when I'm finished, media should contain records with distinct SynthId.
SynthId can be null, I want all nulls to be in media (the distinct should not affect them).
My DAL is EntityFramework, if that will help.
How do I accomplish this in the most efficient way?
Use a grouping query:
var media =
from p in postService.GetMedia(postId)
group p by p.SynthId into g
select g.First();
This will give you the first post in the sequence for each group of records, where the grouping key is the SynthId.
If it's important for you to do a projection (i.e. to use select new { ... }) then you should be able to use the let keyword:
var media =
from p in postService.GetMedia(postId)
group p by p.SynthId into g
let firstPost = g.First()
select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId };
If you want all null values for SynthId to be in their own group, then I would probably filter the first list and then do a concatenation, i.e.:
var media = postService.GetMedia(postId);
var myMedia =
(from p in media
where p.SynthId != null
group p by p.SynthId into g
let firstPost = g.First()
select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId })
.Concat
(from p in media
where p.SynthId == null
select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId });

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

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.

Resources