I have 2 tables in db - one is EmploymentRecords one is EmploymentVerificationRecords
I want to query both tables and return one List
I have a Model (simplified example):
Public Class Record
{
int ID {get; set;}
string name {get; set;}
bool IsVerification {get; set;}
}
I want to have some type of query in LINQ like :
var records = from a in _context.EmploymentRecords
join b in _context.EmploymentVerificationRecords on a.id equals b.id
where a.UserID = 1
select new Record() { .ID = a.id, .name = a.name, .IsVerification = false}
// I also want to select a new Record() for each b found
see - I also want a new Record() added to the results for each record found in the second table , for these results IsVerification would be True
You can select everything from DB as it is selected now (but I would rather use join/into to do that) and then flatten results into one big collection using LINQ to Objects.
Following should do the trick:
var records
= (from a in _context.EmploymentRecords
join b in _context.EmploymentVerificationRecords on a.id equals b.id into bc
where a.UserID = 1
select new {
a = new Record() { ID = a.id, name = a.name, IsVerification = false},
b = bc.Select(x => new Record() { ID = x.ID, name = b.name, IsVerification = true })
}).AsEnumerable()
.SelectMany(x => (new [] { x.a }).Concat(x.b));
Related
I have one problem.
Database Shema
==================
|parts |
==================
| partId |textId |
==================
========================
texts |
========================
|TextId|LanguageId|text|
========================
============================
languages |
============================
|LanguageId|LanguageIsoCode|
============================
I want to map this result to the following object
public long PartId { get; set; }
public Dictionary<string,string> Name { get; set; }
eg.
{
PartId: 32020
Name: {["en": "Blah", "es": "Blah2"]}
}
this is what I have tried, but Im running into TimeOut with this query.
var query = (from p in _context.epc_parts
select new //select first dynamic object
{
PartId = p.PartID,
Code = p.PartName,
Name = (from trans in _context.epc_texts
join lang in _context.epc_languages on trans.LanguageID equals lang.LanguageID
where p.TextID == trans.TextID
select new
{
LanguageId = lang.shortname.ToLower(),
Caption = trans.Caption
})
}).AsEnumerable().Select(x => new SearchPartModel //transform it here when we can use dictionary
{
Code = x.Code,
PartId = x.PartId,
Name = x.Name.ToDictionary(t => t.LanguageId, t => t.Caption)
});
The parts table has about 60k rows for every row there are 7 translations. Navigation properties cant be used because the Shema doesn't use foreign keys and the model is generated from db.
I have solved it with this query. For the whole query it took about 20s to load everything what is ok for this purpose. Im using group by first.
(from p in _context.epc_parts
join trans in _context.epc_texts on p.TextID equals trans.TextID
join lang in _context.epc_languages on trans.LanguageID equals lang.LanguageID
select new
{
PartId = p.PartID,
Code = p.PartName,
Caption = trans.Caption,
LanguageId = lang.shortname.ToLower()
}).AsEnumerable().GroupBy(x => x.PartId).Select(g => new SearchPartModel
{
Code = g.Select(x => x.Code).FirstOrDefault(),
PartId = g.Key,
Name = g.Select(x => new
{
x.LanguageId,
x.Caption
}).Distinct().ToDictionary(y => y.LanguageId, y => y.Caption)
});
from p in _context.epc_parts
join trans in _context.epc_texts on p.TextID equals trans.TextID
join lang in _context.epc_languages on trans.LanguageID equals lang.LanguageID
select new {
PartId = p.PartID,
Code = p.PartName,
Name = new
{
LanguageId = lang.shortname.ToLower(),
Caption = trans.Caption
}
}
That should be better, otherwise in your current implementation for each part you're querying the texts table
I have a linq statement to populate two labels. The thing is, this information comes from two tables. I Have a join to join the two tables, except i cant get my Terms and Conditions from my Campaign table. Its only picking up the RedemptionLog table columns. Anyone to help with this?
MSCDatabaseDataContext MSCDB = new MSCDatabaseDataContext();
var q = from row in MSCDB.Tbl_RedemptionLogs
join d in MSCDB.Tbl_Campaigns on row.CampaignId equals d.CampaignId
orderby row.VoucherCode descending
select row;
var SeshVoucherDisplay = q.First();
lblCode.Text = SeshVoucherDisplay.VoucherCode;
lblTerms.Text = SeshVoucherDisplay
For the SeshVoucherDisplay variable, it only picks up from the RedemptionLogs table, yet i did a join? Any help?
Try something like this :
var SupJoin = from row in MSCDB.Tbl_RedemptionLogs
join d in MSCDB.Tbl_Campaigns on row.CampaignId equals d.CampaignId
orderby row.VoucherCode descending
select new { Id = row.ID, SupplierName = row.SupplierName,
CustomerName = d.CompanyName };
The column names are just for example purpose. Put your own there. And thereafter, you can apply First on it and use that particular variable.
Hope this helps.
Well, by writing select row you asked LINQ to give back to you only row.
If you want both elements, you need to ask for both of them, e.g. by writing select new { row, d }.
In this example
var foo =
new []
{
new { Id = 1, Name = "a" },
new { Id = 2, Name = "b" },
new { Id = 3, Name = "c" }
};
var bar =
new []
{
new { Id = 1, Name = "d" },
new { Id = 2, Name = "e" },
new { Id = 3, Name = "f" }
};
var baz =
from a in foo
join b in bar on a.Id equals b.Id
select new { a, b };
var qux =
from a in foo
join b in bar on a.Id equals b.Id
select new { a, b };
In baz you'll find only a list of foos, in qux you'll find a list of both foos and their bar.
Try this:
var query = (from row in MSCDB.Tbl_RedemptionLogs
join d in MSCDB.Tbl_Campaigns on row.CampaignId equals d.CampaignId)
orderby row.VoucherCode descending
select new
{
columnname = row.columnname
});
When writing select row you relate to the row you defined in from row in MSCDB.Tbl_RedemptionLogs.
However if you want the data from both tables you have to write something similar to this:
select new {
// the properties of row
Redemption = row.redemption,
// the properties of d
Campaign = d.CampaignID // alternativly use may also use row.CampaignID, but I wanted to show you may acces all the members from d also
}
This is my view model
public class ProcurementDisplayData
{
public string Key { get; set;}
public string Value { get; set;}
}
How can I hard code this list. Basically what will be the syntax inside the query
var query = (from u in context.Jobs
join q in context.Quotations on u.QuotationId equals q.QuotationId
join v in context.Vessels on q.VesselId equals v.VesselId
join c in context.Customers on q.CustomerId equals c.CustomerId
where u.JobNo == JobNo
select new List<ProcurementDisplayData>
{
new { Key = "a" ,Value=u.JobNo},
new { Key = "b" ,Value=u.Vessel}
}).ToList();
return query;
Get JobNo and Vessel from database. Then create lists in memory:
var query = from u in context.Jobs
join q in context.Quotations on u.QuotationId equals q.QuotationId
join c in context.Customers on q.CustomerId equals c.CustomerId
where u.JobNo == JobNo
select new { u.JobNo, u.Vessel };
return query.AsEnumerable() // moves further processing to memory
.Select(x => new List<ProcurementDisplayData> {
new { Key = "a", Value = x.JobNo },
new { Key = "b", Value = x.Vessel }
}).ToList();
I have a list cids that I am fetching like this
var cids = _service.Employee.Where(i => i.EmpID == _empID).Select(j => j.ClientID).ToList();
I want to compare this list with Patient Entity and get all the records of patients that matches the clientId in the cid list
Patient Entity is like this
class Patient
{
Int PatientID{ get; set;}
Int ClientID{get; set;}
string PatientName{get; set;}
}
Right now I am doing it like this
foreach(var item in cids)
{
var pp = from p1 in _service.Patients
where p1.ClientId == item
select new PatientDTO
{
PatientID = p1.PatientID,
PatientName = p1.PatientName,
};
prec.Add(pp);
}
Is there a way to do it with Linq without using foreach
You can use Contains on your List (you don't need the ToList, by the way : this would avoid 2 queries on db).
var allPp = _service.Patients.Where(p1 => cids.Contains(p1.ClientId))
.Select(m >= new PatientDTO) {
PatientID = m.PatientID,
PatientName = m.PatientName
});
But the most performant way, in a db world, would be a join
from emp in _service.Employee.Where(i => i.EmpID == _empID)
join patient in _service.Patients on emp.ClientId equals patient.ClientId
select new PatientDTO {
PatientID = patient.PatientID,
PatientName = patient.PatientName,
}
Use Enumberable.Intersect to fetch common records.
var commonClients = cids.Intersect<int>(_service.Patients.Select(x => x.ClientID));
var person = _service.Patients.Where(x => commonClients.Contains(x.ClientID));
The Following is my code when i am fetching the value from the GameByGameTypes and Categories but in table called GameByGameTypes have column CategoryId have NULL value. So i want 0 inplace of NULL
Category objCategory;
var query = (from gametypebygametype in db.GameByGameTypes.Where( x => x.GameTypeId == gametypeid)
join category in db.Categories
on gametypebygametype.CategoryId equals category.CategoryId into joined
from category in joined.DefaultIfEmpty()
select new
{
category.CategoryId ,
category.CategoryName
}
).Distinct();
List<Category> objlistCategory = new List<Category>();
foreach (var item_temp in query)
{
objCategory = new Category();
objCategory.CategoryId = item_temp.CategoryId;
objCategory.CategoryName = item_temp.CategoryName;
objlistCategory.Add(objCategory);
}
Or you can replace
select new
{
category.CategoryId,
category.CategoryName
}
with
select new
{
CategoryId = category.CategoryId ?? 0,
CategoryName = category.CategoryName ?? "",
}
If you use ReSharper - it will 'complain' that ?? 0 part is not needed. Ignore it.
And Linq-code you use is translated to SQL. When you execute it - result is null, but strongly-typed compiler cannot believe in that, and awaits non-nullable value. (this is the process of 'materialization', that fails).
So you just 'hint' compiler, that it could be null.
Here is related question.
You have three ways to work with this:
You can set column in database not null and set default to column 0.
You can set Category property int? CategoryId.
You can change your query to use DefaultIfEmpty with default value
var query = (from gametypebygametype in db.GameByGameTypes.Where( x => x.GameTypeId == gametypeid)
join category in db.Categories
on gametypebygametype.CategoryId equals category.CategoryId into joined
from category in joined.DefaultIfEmpty( new
{
CategoryId=0,
Categoryname=""
})
select new ...
Try using GetValueOrDefault
Category objCategory;
var query = (from gametypebygametype in db.GameByGameTypes.Where( x => x.GameTypeId == gametypeid)
join category in db.Categories
on new {A = gametypebygametype.categoryID.GetValueOrDefault(0)}
equals new {A = category.categoryID}
into joined
from category in joined.DefaultIfEmpty()
select new
{
category.CategoryId ,
category.CategoryName
}
).Distinct();
List<Category> objlistCategory = new List<Category>();
foreach (var item_temp in query)
{
objCategory = new Category();
objCategory.CategoryId = item_temp.CategoryId;
objCategory.CategoryName = item_temp.CategoryName;
objlistCategory.Add(objCategory);
}