Based on the following tables
Sample
Id Name
---------------
S1 SomeName
S2 OtherName
S3 AnotherName
AlreadyUsed
Id
---------
S2
Reference
Id FkId
---------
T1 S1
T2 S1
I want to achieve the following
"select only those entries from Sample table which have no entries in AlreadyUsed and have atleast one entry in
Reference table."
I was able to write query for the first part but confused with the second half. Below is what i could come up with to get "select only those entries from sample table which have no entries in AlreadyUsed table"
var count = 50;
var alreayUsed = from au in repository.GetEntity<AlreadyUsed>()
select au.Id;
var notUsed = (from nu in repository.GetEntity<Sample>()
where !alreadyUsed.Contains(nu.Id)
orderby nu.Name
select new CustomClass
{
CName = nu.Name,
CId = nu.Id
}).Take(count).ToArray();
Also pls. suggest if there is a better way to write the above query.
thanks.
var count = 50;
var alreayUsed = from au in repository.GetEntity<AlreadyUsed>()
select au.Id;
var notUsed = (from nu in repository.GetEntity<Sample>()
where !alreadyUsed.Contains(nu.Id) && nu.References.Count() > 0
orderby nu.Name
select new CustomClass
{
CName = nu.Name,
CId = nu.Id
}).Take(count).ToArray();
Notice that I added "nu.References.Count() > 0"
I assume that you setup the association relationship called References correctly in your data model so that there are many "Reference" objects in for every Sample object.
This should achieve what you are looking for. Of course there are many ways to do it. Personally I'd write it this way.
var items = (from r in repository.GetEntity<Reference>()
join s in repository.GetEntity<Sample>()
on r.FkId equals s.Id
where !repository.GetEntity<AlreadyUsed>().Contains(s.Id)
orderby s.Name
select new CustomClass
{
CName = s.Name,
CId = s.Id
})
.Take(count)
.ToArray();
You should be able to use the same technique from your alreadyUsed sample. EG:
var reference = from r in repository.GetEntity<Reference>()
select r.Id;
var notUsed = (from nu in repository.GetEntity<Sample>()
where !alreadyUsed.Contains(nu.Id)
&& reference.Contains(nu.Id)
select new CustomClass
{
CName = nu.Name,
CId = nu.Id
}).Take(count).ToArray();
However, if you do have an association made between the Sample table and the Reference table, then you should probably use Paul's method.
Related
I am using below code to join two tables based on officeId field. Its retuning 0 records.
IQueryable<Usage> usages = this.context.Usage;
usages = usages.Where(usage => usage.OfficeId == officeId);
var agencyList = this.context.Agencies.ToList();
var usage = usages.ToList();
var query = usage.Join(agencyList,
r => r.OfficeId,
a => a.OfficeId,
(r, a) => new UsageAgencyApiModel () {
Id = r.Id,
Product = r.Product,
Chain = a.Chain,
Name = a.Name
}).ToList();
I have 1000+ records in agencies table and 26 records in usage table.
I am expecting 26 records as a result with chain and name colums attached to result from agency table.
Its not returning anything. I am new to .net please guide me if I am missing anything
EDIT
#Tim Schmelter's solution works fine if I get both table context while executing join. But I need to add filter on top of usage table before applying join
IQueryable<Usage> usages = this.context.Usage;
usages = usages.Where(usage => usage.OfficeId == officeId);
var query = from a in usages
// works with this.context.usages instead of usages
join u in this.context.Agencies on a.OfficeId equals u.OfficeId
select new
{
Id = a.Id,
Product = a.Product,
Chain = u.Chain,
Name = u.Name
};
return query.ToList();
Attaching screenshot here
same join query works fine with in memory data as you see below
Both ways works fine if I add in memory datasource or both datasource directly. But not working if I add filter on usages based on officeId before applying join query
One problem ist that you load all into memory first(ToList()).
With joins i prefer query syntax, it is less verbose:
var query = from a in this.context.Agencies
join u in this.context.Usage on a.OfficeId equals u.OfficeId
select new UsageAgencyApiModel()
{
Id = u.Id,
Product = u.Product,
Chain = a.Chain,
Name = a.Name
};
List<UsageAgencyApiModel> resultList = query.ToList();
Edit: You should be able to apply the Where after the Join. If you still don't get records there are no matching:
var query = from a in this.context.Agencies
join u in this.context.Usage on a.OfficeId equals u.OfficeId
where u.OfficeId == officeId
select new UsageAgencyApiModel{ ... };
The following code can help to get the output based on the ID value.
Of course, I wrote with Lambda.
var officeId = 1;
var query = context.Agencies // your starting point - table in the "from" statement
.Join(database.context.Usage, // the source table of the inner join
agency => agency.OfficeId, // Select the primary key (the first part of the "on" clause in an sql "join" statement)
usage => usage.OfficeId , // Select the foreign key (the second part of the "on" clause)
(agency, usage) => new {Agency = agency, Usage = usage }) // selection
.Where(x => x.Agency.OfficeId == id); // where statement
I have this Join :
var mycust= db.CUSTOMER.Where(x => x.NAME.Contains(nameid)).ToList();
var CancCustomer = (from cust in myCust
join ip in db.IPS on must.ID equals ip.CUSTOMER_ID
select new JoinObj {ID = cust.ID, NAME = cust.NAME, LASTNAME = cust.LASTNAME,
TYPE_ID = ip.TYPE_ID, TYPE2_ID = ip.TYPE2_ID,
SERVICE_ID = ip.SERVICE_ID , REASON = ip.REASON }).ToList();
This code returns the first linq result multiple times? What am I missing? Thanks.
Instead of Where, you should use SingleOrDefault/Single - these would indeed return a single row into your mycust variable.
SingleOrDefault would put a null into the variable if no such customers were found (and assuming a Customer is a reference type - if it were a value type, it would be the default value for the type). Single would throw an exception if no items were found or more than one were found, which could be very useful in finding errors in your data (such as duplicate customer records).
Additionally, it is likely your ip table has multiple matching records for a customer - which is why you would be seeing multiple records being returned from your select.
You have multiple Duplicate Record received Then Try For following quires
var mycust= db.CUSTOMER.Where(x => x.NAME.Contains(nameid)).ToList();
var CancCustomer = (from cust in myCust
join ip in db.IPS on cust.ID equals ip.CUSTOMER_ID
select new JoinObj {ID = cust.ID, NAME = cust.NAME, ASTNAME=cust.LASTNAME, TYPE_ID = ip.TYPE_ID, TYPE2_ID = ip.TYPE2_ID, SERVICE_ID = ip.SERVICE_ID , REASON = ip.REASON }).distinct().ToList();
Other Wise Multiple record then You Get One Record for You following Query
var mycust= db.CUSTOMER.Where(x => x.NAME.Contains(nameid)).ToList();
var CancCustomer = (from cust in myCust
join ip in db.IPS on must.ID equals ip.CUSTOMER_ID
select new JoinObj {ID = cust.ID, NAME = cust.NAME, LASTNAME = cust.LASTNAME, TYPE_ID = ip.TYPE_ID, TYPE2_ID = ip.TYPE2_ID, SERVICE_ID = ip.SERVICE_ID , REASON = ip.REASON }).distinct().FirstOrDefault();
I am using Entity Framework to work with my DB and I need help forming a LINQ query that will help me to get columns LoginId and AccNumber. I need only 1 LoginId for every single AccNumber, doesn't matter which LoginId it is. As it stands now, there are about 800K LoginIds and only 5000 AccNumber. Therefore, at the end I need 1 AccNumber associated with 1 LoginId. So I should have 5000 rows and 2 columns.
Here are the tables that I need joined:
Item
ItemId, AccNumber, other irrelevant columns
Block_Item
ItemId, BlockId, other irrelevant columns
Bookversion_Block
BookversionId, BlockId, other irrelevant columns
Sudent
LoginId, BookversionId, other irrelevant columns
Ideally, I want to replicate this SQL query using LINQ (just trying to provide as much info as possible)
select
LoginId,
AccessionNumber
from Item I
outer apply (select top 1 * from Block_Item where I.ItemId = ItemId) BI
outer apply (select top 1 * from BookletVersion_Block where BlockId = BI.BlockId) BVB
outer apply (select top 1 LoginId from Student where BookletVersionId = BVB.BookletVersionId) ST
Here is what I tried, however, the results that I get back are not correct and I get back like 183,000 records and it takes like 10 minutes to execute this. This line "var uniques = q.ToList();" is the one taking a long time.
using (var context = new MyContext())
{
context.Database.CommandTimeout = 1200;
var listOfAccessionNumbers = GetListOfAllAccessionNumbers(context);
var q = (from items in context.Items
join blockItem in context.Block_Item
on items.ItemId equals blockItem.ItemId into bi
join bookletVersion in context.BookletVersion_Block
on bi.Select(x => x.BlockId).FirstOrDefault() equals bookletVersion.BlockId into BVB
join student in context.Students
on BVB.Select(x => x.BookletVersionId).FirstOrDefault() equals student.BookletVersionId into st
//'VH098334'
select new { LoginId = st.Select(x => x.LoginId).FirstOrDefault().ToString(),
AccNum = items.AccessionNumber.ToString() });
**var uniques = q.ToList();**
IList<string> listOfLogins = new List<string>();
foreach (var accessionNumber in listOfAccessionNumbers)
{
var i = q.ToList().Find(x => x.AccNum.Contains(accessionNumber));
listOfLogins.Add(i.LoginId);
}
}
Try to separate your linq operations, to hopefully see which one is taking the longest and where its going wrong.
Also, I suggest using a dictionary with accNumber as key and LoginID as value so you can make sure each accNumber is associated with 1 and only 1 LoginID.
Dictionary<string, string> uniques = new Dictionary<string, string>();
var q = (from items in context.Items
join bi in context.Block_Item
on items.ItemId equals bi.ItemId
select items).ToList();
//var first = bi.Select(x => x.BlockId).FirstOrDefault();
var val = (from b in context.BookletVersion_Block.Select(bv => bv.BlockId)
join a in q on b equals q.FirstOrDefault().BlockId into BVB
join c in context.Students on BVB.FirstOrDefault().BookletVersionId equals c.BookletVersionId into st
select new { LoginId = st.Select(x => x.LoginId).FirstOrDefault().ToString(), AccNum = a.AccessionNumber.ToString() });
//if (!uniques.ContainsKey(bi.AccNum))
//uniques.Add(val.AccNum, val.LoginId);
uniques = val.ToDictionary(c => c.AccNum, c => c.LoginId);
Haven't tested it, so let me know the time taken and whether you get correct values.
The dictionary should ensure you get 5000 values, but I am not sure why it is taking so long, but lets fix the number of records problem first.
I want to compare two lists and assign 1st list to another in case of requirement.
var getdetail=_readonlyservice.getdetail().ToList();
foreach(var item in docdetail)
{
var temp=getdetail.firstordefualt(i=>i.Id=item.Id)
if(temp==null) continue;
item.code=temp.code;
}
I want to implement top statements in linq .any help ?
Think so..
var getdetail=_readonlyservice.getdetail().ToList();
var tempList = from dd in context.docdetail
join g in context.getdetail on dd.Id equals g.Id
select new // Your type
{
// Columns...
Code = g.Code
}
I believe you are trying to do like the way I did, although I was going to join table.
var result = (from e in DSE.employees
join d in DSE.departments on e.department_id equals d.department_id
join ws in DSE.workingshifts on e.shift_id equals ws.shift_id
select new
{
FirstName = e.FirstName,
LastName = e.LastName,
Gender = e.Gender,
Salary = e.Salary,
Department_id = e.department_id,
Department_Name = d.department_name,
Shift_id = ws.shift_id,
Duration = ws.duration,
}).ToList();
// TODO utilize the above result
I was using DTO method to do this. And then you return result(as this case is result).
You may view the whole question and solution here.
As this case, you are not required to put foreach loop, as the query said from every row in yourdatabase.table
I have two tables. Table One contains a list of Areas, and Table Two contains a list of Samples, with each Sample row containing Area_ID as a Foreign Key.
I need to retrieve all the records in my Area table with only the most recent corresponding Sample Status. I have this query, but it just returns one Area with the most recent sample from the Sample table:
var result = (
from a in db.area
join c in db.sample
on a.location_id equals c.location_id
select new
{
name = a.location_name,
status = c.sample_status,
date = c.sample_date
}).OrderByDescending(c => c.date).FirstOrDefault();
A solution could be filtering your second DbSet:
var result = from a in db.area
join c in db.sample.Where(s=>s.location_id==a.location_id).OrderByDescending(c => c.sample_date).Take(1)
on a.location_id equals c.location_id
select new
{
name = a.location_name,
status = c.sample_status,
date = c.sample_date
};
Another solution could be applying a group join:
var result = from a in db.area
join c in db.sample
on a.location_id equals c.location_id into samples
let sample=samples.OrderByDescending(c => c.sample_date).FirstOrDefault()
select new
{
name = a.location_name,
status = sample.sample_status,
date = sample.sample_date
};
If you use navigation properties could be even easier. Supposing you have a one to many relationship between Area and Sample:
var result =from a in db.area
let sample= a.Samples.OrderByDescending(c => c.sample_date).FirstOrDefault()
select new
{
name = a.location_name,
status = sample.sample_status,
date = sample.sample_date
};