Select multiple columns from Linq query - c#

I have two tables. Customer and CustomerBenefits.
Fields in each table
Customer - ID, Name, Address, Country etc
CUstomerBenefits - CustomerID, BenefitID (Both IDs have a relation to their relevant tables)
I am trying to list the customers and get the Benefit Details
IEnumerable<CustomerBenefit> GetData = from c in MyContext.CUstomerBenefits
where c.CustomerId == UserId & c.Active = true
orderby c.CustomerBenefit.BenType descending
select new {???? };
For the Select, Ive tried
select new {c.Benefit.Name }
but get the error
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)
If i change IEnumerable<CustomerBenefit> to IEnumerable<dynamic> i get no errors but when the data is bound to my gridview i get the error that a field is not found.
How could i keep IEnumerable<CustomerBenefit> and select the columns i require?

You wrote:
CUstomerBenefits - CustomerID, BenefitID (Both IDs have a relation to
their relevant tables)
I interpret this as meaning that there is a table CustomerBenefit that contains, well, benefits and that the CUstomerBenefits table in turn is a link between the customer and the benefits. And now you want to get a list of all the benefits that a specific customer has?
This should do the trick:
IEnumerable<CustomerBenefit> GetData =
from c in MyContext.CUstomerBenefits
where c.CustomerId == UserId && c.Active == true
orderby c.CustomerBenefit.BenType descending
select c.CustomerBenefit;

Use: select c to get all of the column values or:
select new CustomerBenefit {CustomerID = c.CustomerID}; etc

var HOQuotePremiums = (from holoc in objRes.ResHO.HOLocations
from cst in ((HOLocation)holoc).HOBuildings
select new
{
RequestId = cst.HOPremium.RequestId,
BasePremium = Convert.ToInt32(cst.HOPremium.BasePremium),
PersonalLiabilityPremium = cst.HOPremium.PersonalLiabilityPremium,
MedicalPaymentPremium = cst.HOPremium.MedicalPaymentPremium,
FinalPremium = objRes.ResHO.FinalPremium,
WithoutAOPDeductibleFinalPremium = cst.HOPremium.WithoutAOPDeductibleFinalPremium,
SubTotalPremium = objRes.ResHO.FinalPremiumWithoutFeeTax,
LocationID = holoc.LocationID,
BuildingID = cst.BuildingID,
IsMinimumPremium = cst.HOPremium.IsMinimumPremium,
MinimumPremium = cst.HOPremium.MinimumPremium,
SubTotalPremiumWithoutMinimumPremium = cst.HOPremium.SubTotalPremiumWithoutMinimumPremium,
FinalRate=cst.HOPremium.FinalRate,
}).ToList();
Please try this .

Related

Linq Join query returning empty dataset

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

LINQ Join gives only first result multiple times

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();

LINQ Query To Join Two Tables and Select Most Recent Records from Table B corresponding to Table A

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
};

Select list with linq

I have 2 tables in a database, and one class in C# (Letter).
Tables: tblUser(Id, Name), tblLetter(Id, UserId, Title)
Letter: (Id, Title, UserName)
I want select data with linq, and use this code:
List<Letter> lst = new List<Letter>();
lst = (from l in l.tblLetter.ToList()
select new {l.Id, l.Title, UserName = l.tblUser.Name}
).ToList();
and:
List<Letter> lst = new List<Letter>
(from l in l.tblLetter.ToList()
select new {l.Id, l.Title, UserName = l.tblUser.Name});
but get this error:
Cannot implicitly convert type...
As #SnowYetis comments, you are actually selecting an instance of a new, anonymous type in your code. That's what the syntax new { ... } does. Notice that there's no type name after the new directive.
If your Letter type has the properties Id, Title, UserName then all you need to do is change new { ... } to new Letter { ... }.
If not, then we probably need more information than you're giving us—for example, the definition of the Letter type.
There are a few issues in your code:
l.tblLetter.ToList() returns all records from your table. You typically don't call ToList() until the end of your query, to get just the data you need and no more.
You want to do a join between the two tables to get the matching user name.
If you want to return a collection of Letter, you can create instances of that in your select statement instead of creating an anonymous type.
Try this:
var lst = (from l in l.tblLetter
join u in tblUser on l.UserId equals u.Id
select new Letter
{
Id = l.Id,
Title = l.Title,
UserName = u.Name
}).ToList();

Joining two IQueryable variables of different types together using LINQ

The columns names and types are identical, however it's coming from two separate entities. Here is a simplified example:
--Query View
var v_res = from s in db.V_CMUCUSTOMER
select s;
--Values from table less values from view
var res = from s in db.CMUCUSTOMERs
where !(from v in v_res
select v.ID).Contains(s.ID)
select s;
--join table and view values into one variable
var res_v_res = (from c in res
select c).Union(from v in v_res
select v);
I get the following error however:
Instance argument: cannot convert from 'System.Linq.IQueryable' to System.Linq.ParallelQuery
If you specify a new anonymous type and use ToList() for both then you should be able to Union them as follows :
var v_res = (from s in db.V_CMUCUSTOMER
select new { custName = s.customer_name custAddress = s.address}).ToList();
--Values from table less values from view
var res = (from s in db.CMUCUSTOMERs
where !(from v in v_res
select v.ID).Contains(s.ID)
select new { custName = s.customer_name custAddress = s.address }).ToList();
--join table and view values into one variable
var res_v_res = v_res.Union(res);
This may be onerous if there are dozens of columns but should still work.
When I run a similar query in LINQPad, I get an error message claiming that s in Contains(s.ID) is not defined in this context.
If I replace && with where all queries are successfully executed.

Categories

Resources