Problems with selecting 2 column values in Linq to Entity - entity-framework

Hi I am trying to select the values of two columns which are second driver and price but I am getting error: Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IQueryable'. An explicit conversion exists (are you missing a cast?)
Below is the code:
public IQueryable<Event> GetSecondDriverOption(int eventID)
{
ApextrackdaysEntities entity = new ApextrackdaysEntities();
IQueryable<Event> SecondDriver = from p in entity.Events
where p.ID == eventID
select new{ p.SecondDriver,
p.SecondDriverPrice};
return SecondDriver;
}
Any help or suggestions will be appreciated thnx

You cannot use projection when you expect IQueryable<Event> where Event is your mapped type. You must either select Event :
IQueryable<Event> SecondDriver = from p in entity.Events
where p.ID == eventID
select p;
Or you must create new type and project data to a new type:
public class EventDto
{
public Driver SecondDriver { get; set; }
public Price SecondDriverPrice { get; set; }
}
and redefine your method:
public IQueryable<EventDto> GetSecondDriverOption(int eventID)
{
ApextrackdaysEntities entity = new ApextrackdaysEntities();
IQueryable<EventDto> SecondDriver = from p in entity.Events
where p.ID == eventID
select new EventDto
{
SecondDriver = p.SecondDriver,
SecondDriverPrice = p.SecondDriverPrice
};
return SecondDriver;
}

You cannot return anonymous objects. Try like this:
public IQueryable<Event> GetSecondDriverOption(int eventID)
{
ApextrackdaysEntities entity = new ApextrackdaysEntities();
var seconDriver =
from p in entity.Events
where p.ID == eventID;
select p;
return secondDriver;
}

Related

How to join tables using linq and entity framework

In the code given below i want to join all the three table i get the data by joining the table but while displaying the data only the data of CK_Model is displayed. Please help
public List<CK_Model> GetDetails()
{
try
{
using (var entities = new MobileStore2020Entities())
{
var details = from a in entities.CK_Model
join b in entities.CK_Brand
on a.BrandID equals b.BrandID
join c in entities.CK_Stock
on a.ModelID equals c.ModelID
select new
{
ModelID = a.ModelID,
ModelName = a.ModelName
};
return details.ToList();
Thank You.
If I understand correctly you want to return data from all 3 tables by accessing them through your context. If you want to do this you have change your method's return type. For example create a new class with all 3 item types
public class DetailsItemType
{
public CK_Model Model{ get; set; }
public CK_Brand Brand { get; set; }
public CK_Stock Stock { get; set; }
}
Then change your method's return type to DetailsItemType and you'll have something like the following
public List<DetailsItemType> GetDetails()
{
using (var entities = new MobileStore2020Entities())
{
var details = from a in entities.CK_Model
join b in entities.CK_Brand
on a.BrandID equals b.BrandID
join c in entities.CK_Stock
on a.ModelID equals c.ModelID
select new DetailsItemType
{
Model= a,
Brand = b,
Stock = c
};
return details.ToList();
}
}
Now every time you call GetDetails() you can access all 3 tables. For example
var details = GetDetails();
var model = details.Model;
var brand = details.Brand;
var stock = details.Brand;

Include with additional param on join

I have many Nations and for each Nation i have a lot of Teams.
The GetTeam endpoint in team controller retrieve a single Team and its related Nation. Via LINQ the query is this:
Context.Teams.Include(t => t.Nation).First(t => t.Id.Equals(__id))
The resulting JSON is what I want:
{"team":{"name":"Team1","nation":{"id":1,"name":"Nation1"}}
Let's say now that the property "name", both in Team and Nation model is dropped and a new model relation is created, with Translation.
What I want now is to retrieve the same JSON, but with a different query based on culture.
Gettin crazy understand how I can achieve it with include.
How can I compose this query in LINQ ?
select *
from Teams inner join
Translations TeamTr on Teams.id = TeamTr .id and TeamTr .culture = "IT" inner join
Nations on Teams.nation_id = Nations.id inner join
Translations NationTr on Nations .id = NationTr .id and NationTr .culture = "IT"
And compose the resulting data as JSON above?
for example:
(from team in Context.Teams
join teamTr in Context.Translations on team.id equals teamTr.id
join nation in Context.Nations on team.nation_id equals nations.id
join nationTr in Context.Translations on nation.id equals nationTr.id
where teamTr.culture == "IT" && nationTr.culture == "IT"
select new
{
teamName = team.name,
nationName = nation.name
}).ToList();
Nice catch tdayi.
First of all I've created a new class, that will be the container of the linq result:
public class TeamDetailLinqDto
{
public Team Team { get; set; }
public Translation TeamTranslation { get; set; }
public Nation Nation { get; set; }
public Translation NationTranslation { get; set; }
}
and this is the linq query:
public IQueryable<TeamDetailLinqDto> GetTeams()
{
var result = from team in Context.Teams
join teamTranslation in Context.Translations on
new { Id = team.Id, Locale = "IT" }
equals new { Id = teamTranslation.EntityId, Locale = teamTranslation.Locale }
join nation in Context.Nations on team.NationId equals nation.Id
join nationTranslation in Context.Translations on
new { Id = nation.Id, Locale = "IT" }
equals new { Id = nationTranslation.EntityId, Locale = nationTranslation.Locale }
select new TeamDetailLinqDto
{
Team = team,
TeamTranslation = teamTranslation,
Nation = nation,
NationTranslation = nationTranslation
};
return result;
}

list in entity framework and webapi

I am trying to return employee with three column in .net webapi with entity framework but return gives error saying cannot convert type pf anonymous to emp ..what I am missing
public List<EMPLOYEE_DTLS> GetLoginInfo(string UserId)
{
var result = (from emp in db.EMPLOYEE_DTLS
where emp.UserId == UserId
select new
{
emp.FullName,
emp.Role,
emp.Designation
}).ToList();
return result;
}
You should use a DTO to return the list.
public class EmployeeDTO
{
public string FullName {get; set;}
public string Role {get; set;}
public string Designation {get; set;}
}
public List<EmployeeDTO> GetLoginInfo(string UserId)
{
var result = (from emp in db.EMPLOYEE_DTLS
where emp.UserId == UserId
select new EmployeeDTO
{
FullName = emp.FullName,
Role = emp.Role,
Designation = emp.Designation
}).ToList();
return result;
}
Your method returns List<EMPLOYEE_DTLS>, but you are trying to return List of anonymous type.
Assuming you EMPLOYEE_DTLS class has properties FullName, Role and Designation change the type you are selecting:
public List<EMPLOYEE_DTLS> GetLoginInfo(string UserId)
{
var result = (from emp in db.EMPLOYEE_DTLS
where emp.UserId == UserId
select new EMPLOYEE_DTLS
{
FullName = emp.FullName,
Role = emp.Role,
Designation = emp.Designation
}).ToList();
return result;
}

IQueryable.Select to a List type sub POCO

I have an Entity Framework model in which there is a "Customers" and a "CustomerPhones" table. A customer can have multiple phone numbers so the "Customer" entity has a collection of "Phone". I can query the model with no problem :
using (CustomerEntities context = new CustomerEntities())
{
Customer customer = context.Customers.FirstOrDefault();
CustomerPhone phone = customer.Phones.FirstOrDefault();
MessageBox.Show(customer.Name + " " + phone.Number);
}
The model is too complex for what I need to do (even though my example is basic) so I'm trying to boil it down to simpler POCOs. Here are the 2 simple classes :
public class SimplePhone
{
public int Id { get; set; }
public string Number { get; set; }
}
public class SimpleCustomer
{
public int Id { get; set; }
public string Name { get; set; }
//Phones is a list because a single Customer can have multiple phone numbers
public List<SimplePhone> Phones { get; set; }
}
I can populate the simple properties of the object using the "Select" method of "IQueryable" :
using (CustomerEntities context = new CustomerEntities())
{
IQueryable<SimpleCustomer> customers = context.Customers.Select(
c => new SimpleCustomer
{
Id = c.Id,
Name = c.Name
}
);
SimpleCustomer customer = customers.FirstOrDefault();
MessageBox.Show(customer.Name);
}
So my question is pretty simple : how can I populate the "Phones" property which is a list?
using (CustomerEntities context = new CustomerEntities())
{
IQueryable<SimpleCustomer> customers = context.Customers.Select(
c => new SimpleCustomer
{
Id = c.Id,
Name = c.Name
Phones = ///????
}
);
SimpleCustomer customer = customers.FirstOrDefault();
SimplePhone phone = customer.Phones.FirstOrDefault();
MessageBox.Show(customer.Name + " " + phone.Number);
}
Let me know if I'm unclear and/or you need more details.
Thanks!
I'm not sure if there isn't something more to your question, but as far as I understand, you can just call ToList and it will be materialized as a list:
IQueryable<SimpleCustomer> customers =
context.Customers.Select(c => new SimpleCustomer
{
Id = c.Id,
Name = c.Name,
Phones = c.Phones.Select(p => new SimplePhone
{
Id = p.Id, // Unless you want the custom Id, i.e. c.Id
Number = p.Number
}).ToList();
});

Converting ESQL to LINQ to Entities. Sort by related entities

I am using EF + RIA and unfortunately meet some problems with sorting by related entities.
For such purpose there is ESQL query that I implemented (found only this solution):
var queryESQL = string.Format(
#" select VALUE ent from SomeEntities as ent
join Attributes as ea ON ea.EntityId = ent.Id
where ea.AttributeTypeId = #typeId
order by ea.{0} {1}", columnName, descending ? "desc" : "asc");
var query = ObjectContext.CreateQuery<SomeEntity>(queryESQL, new ObjectParameter("typeId", attributeTypeId));
Tables have following structure:
<Attribute>:
int Id;
decimal DecimalColumn;
string StringColumn;
int EntityId;
int AttributeTypeId;
<SomeEntity>:
int Id;
string Name;
Is there any way to rewrite this stuff(sorting), using LINQ to Entities approach?
Here's my attempt, I can't guarantee it will work. I need to think more on how to get a dynamic column name, I'm not sure on that one. EDIT: you can use a string for the order column.
int typeId = 1115;
bool orderAscending = false;
string columnName = "StringColumn";
var query = from ent in SomeEntities
join ea in Attributes on ea.EntityId = ent.Id
where ea.AttributeTypeId = typeId;
if(orderAscending)
{
query = query.OrderBy(ea => columnName).Select(ea => ea.Value);
}
else
{
query = query.OrderByDescending(ea => columnName).Select(ea => ea.Value);
}
var results = query.ToList(); // call toList or enumerate to execute the query, since LINQ has deferred execution.
EDIT: I think that ordering after the select stops is from ordering by. I moved the select statement to after the order by. I also added the "query =", but I'm not sure if that is needed. I don't have a way to test this at the moment.
EDIT 3: I fired up LINQPad today and made a few tweaks to what I had before. I modeled your data in a Code-first approach to using EF and it should be close to what you have.
This approach works better if you're just trying to get a list of Attributes (which you aren't). To get around that I added an Entity property to the MyAttribute class.
This code works in LINQPAD.
void Main()
{
// add test entities as needed. I'm assuming you have an Attibutes collection on your Entity based on your tables.
List<MyEntity> SomeEntities = new List<MyEntity>();
MyEntity e1 = new MyEntity();
MyAttribute a1 = new MyAttribute(){ StringColumn="One", DecimalColumn=25.6M, Id=1, EntityId=1, AttributeTypeId = 1, Entity=e1 };
e1.Attributes.Add(a1);
e1.Id = 1;
e1.Name= "E1";
SomeEntities.Add(e1);
MyEntity e2 = new MyEntity();
MyAttribute a2 = new MyAttribute(){ StringColumn="Two", DecimalColumn=198.7M, Id=2, EntityId=2, AttributeTypeId = 1, Entity=e2 };
e2.Attributes.Add(a2);
e2.Id = 2;
e2.Name = "E2";
SomeEntities.Add(e2);
MyEntity e3 = new MyEntity();
MyAttribute a3 = new MyAttribute(){ StringColumn="Three", DecimalColumn=65.9M, Id=3, EntityId=3, AttributeTypeId = 1, Entity=e3 };
e3.Attributes.Add(a3);
e3.Id = 3;
e3.Name = "E3";
SomeEntities.Add(e3);
List<MyAttribute> attributes = new List<MyAttribute>();
attributes.Add(a1);
attributes.Add(a2);
attributes.Add(a3);
int typeId = 1;
bool orderAscending = true;
string columnName = "StringColumn";
var query = (from ent in SomeEntities
where ent.Attributes.Any(a => a.AttributeTypeId == typeId)
select ent.Attributes).SelectMany(a => a).AsQueryable();
query.Dump("Pre Ordering");
if(orderAscending)
{
// query = is needed
query = query.OrderBy(att => MyEntity.GetPropertyValue(att, columnName));
}
else
{
query = query.OrderByDescending(att => MyEntity.GetPropertyValue(att, columnName));
}
// returns a list of MyAttributes. If you need to get a list of attributes, add a MyEntity property to the MyAttribute class and populate it
var results = query.Select(att => att.Entity).ToList().Dump();
}
// Define other methods and classes here
}
class MyAttribute
{
public int Id { get; set; }
public decimal DecimalColumn { get; set; }
public string StringColumn { get; set; }
public int EntityId { get; set; }
public int AttributeTypeId { get; set; }
// having this property will require an Include in EF to return it then query, which is less effecient than the original ObjectQuery< for the question
public MyEntity Entity { get; set; }
}
class MyEntity
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<MyAttribute> Attributes { get; set; }
public MyEntity()
{
this.Attributes = new List<MyAttribute>();
}
// this could have been on any class, I stuck it here for ease of use in LINQPad
// caution reflection may be slow
public static object GetPropertyValue(object obj, string property)
{
// from Kjetil Watnedal on http://stackoverflow.com/questions/41244/dynamic-linq-orderby
System.Reflection.PropertyInfo propertyInfo=obj.GetType().GetProperty(property);
return propertyInfo.GetValue(obj, null);
}