Linq lambda query to select child and specify parent data - entity-framework

I have two tables, User and Group. I need to select user table and name of the group through lambda expression, and the return type of the method is User table
Below is my schema structure for user
Below is my schema structure for Group table

Try something like;
var query = yourContext.Users.Select(user => new
{
User = user,
GroupName = user.Group.Name
});

Related

Yii2: How to do a simple join query?

I am learning how to do simple queries using the Yii2 framework. I use PostgreSQL.
I am trying to join two tables and get the data from both tables with a where condition.
The tables are called Admins and Persons.
The join use field called idadm.
The condition is idadm = 33. This works great but the result has data only from the Admins table and I need data from the other table.
Here is my example:
$query = \app\models\Admins::find()
->select('*')
->leftJoin('persons', 'persons.idadm = admins.idadm')
->where(['admins.idadm' => 33])
->with('persons')
->all();
I am following the Yii2 official guide: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html
Update: Here I show the updated code that doesn't solve de problem:
You need to write all column name in select().
$query = \app\models\Admins::find()
->select('admin.*,persons.*') // make sure same column name not there in both table
->leftJoin('persons', 'persons.idadm = admins.idadm')
->where(['admins.idadm' => 33])
->with('persons')
->all();
And also you need to define person table attributes in Admin model.
Second way is get records as array,so you dont need to define attributes in Admin model.
$query = \app\models\Admins::find()
->select('admin.*,persons.*') // make sure same column name not there in both table
->leftJoin('persons', 'persons.idadm = admins.idadm')
->where(['admins.idadm' => 33])
->with('persons')
->asArray()
->all();
Ensure that active record has required relations, e.g. something like follows:
class Admins extends \yii\db\ActiveRecord {
public function table() {
return "admins";
}
public function getPersons()
{
return $this->hasMany(Person::className(), ['idadm' => 'idadm']);
}
}
class Person extends \yii\db\ActiveRecord {
public function table() {
return "persons";
}
}
Then use joinWith to build query:
$query = Admins::find()
->joinWith('persons')
->limit(1);
$result = $query->createCommand()->getSql();
echo $result;
Here is produced query:
SELECT `admins`.* FROM `admins`
LEFT JOIN `person` ON `admins`.`idadm` = `person`.`idadm` LIMIT 1

Not able to use IN query in LINQ with Entity Framework

I am using EF Framework to retrieve the data from SQL DB.
Sub Request Table looks like below:
In this table "org_assigneddept" is foreign key to another Department Table.
I have list of Departments as Input and I want to retrieve only those rows from DB whose org_assigneddept is matching the list.
Please find my whole code:-
private List<EventRequestDetailsViewModel> GetSummaryAssignedDeptEventRequests(List<EmpRoleDeptViewModel> vmDept)
{
List<EventRequestDetailsViewModel> vmEventRequestDeptSummary = new List<EventRequestDetailsViewModel>();
RequestBLL getRequestBLL = new RequestBLL();
Guid subRequestStatusId = getRequestBLL.GetRequestStatusId("Open");
using (var ctxGetEventRequestSumm = new STREAM_EMPLOYEEDBEntities())
{
vmEventRequestDeptSummary = (from ers in ctxGetEventRequestSumm.SubRequests
where vmDept.Any(dep=>dep.DeptId == ers.org_assigneddept)
select new EventRequestDetailsViewModel
{
SubRequestId = ers.org_subreqid
}).ToList();
}
}
It is giving the following error at the LINQ Query level:-
System.NotSupportedException: 'Unable to create a constant value of
type 'Application.Business.DLL.EmpRoleDeptViewModel'. Only primitive
types or enumeration types are supported in this context.'
Please let me know as how can I achieve the result
You cannot pass the department VMs to SQL, it doesn't know what those are.
// Extract the IDs from the view models.. Now a list of primitive types..
var departmentIds = vmDept.Select(x => x.DeptId).ToList();
then in your select statement...
..
where departmentIds.Contains(id=> id == ers.org_assigneddept)
..

Fetch only key value from EF association

I've set up a many-to-many association between two tables based on a third table that just holds a pair of key values. Now I'd like to do a query that groups the right tables key values by the lefts without needing other data.
LeftTable { LeftID, LeftField1, LeftField2 }
JoinTable { LeftID, RightID}
RightTable { RightID, RightField1, RightField2 }
Is there any way to essentially just query the JoinTable and get all the 'RightIDs' grouped by the 'LeftIDs' without the SQL trying to fetch the fields from either side?
The JoinTable is not an entity in its own right in the model, but is mapped to the association.
I've experimented a bit with both using ObjectQuery and EntityCommand (ESQL) and both seem to still load in the other fields by joining to RightTable which I don't need.
My ESQL looks something like:
SELECT lt.LeftID, (SELECT rt.RightID
FROM NAVIGATE(lt, MyModel.LeftToRightAssoc, RightTable) as rt)
FROM MyEntities.LeftTable as lt;
but the generated SQL is still fetching in RightField1 and RightField2.
Surely there must be a simpler way to do this?
Assuming that your class Left has a navigation property Rights (a collection of Right entities) you could try this:
var list = context.Lefts.Select(l => new
{
LeftId = l.LeftId,
RightIds = l.Rights.Select(r => r.RightId)
});
foreach (var item in list)
{
Console.WriteLine("LeftId = {0}", item.LeftId);
foreach (var rightId in item.RightIds)
{
Console.WriteLine("RightId = {0}", rightId);
}
}
You would get a collection of anonymous type objects where each element has the LeftId and a collection of corresponding RightIds. This query should not touch the other fields like RightField1, etc. Instead of an anonymous type you could also create your own custom type and then project into this type in the query above.

Entity Framework limit length of a returned nvarchar column

I want to limit the length of a column in an EF query, ala:
var query = from ce in entities.ContactEvents
.Include("Person")
.Include("Orders")
where ce.PersonID = personID
orderby ce.DateTimeContact descending
select new ContactEvent
{
ID = ce.ID,
DateTimeContact = ce.DateTimeContact,
Description = ce.Description.Substring(0, 500),
Orders = ce.Orders
};
The query fails because the EF can't project the complex type Orders.
The entity or complex type 'Model.ContactEvent' cannot be constructed in a LINQ to Entities query.
I've tried a few different ways to do the same thing such as use an explicit join in the LINQ expression but so far I always hit a snag populating the Orders collection in the select projection.
Any ideas on how I can construct my query? Ideally I don't even want to use a select projection but I'm assuming I need to in order to be able to limit the length of the description column returned from the database.
You cannot project to entity types. That is the limitation. If you want to return projection (calling select new) you must either return anonymous type or custom non entity type. If you want to return entity type you must always return whole column from linq-to-entities. You can try to trim the column after object is materialized by using:
var data = (from ce in entities.ContactEvents
.Include("Person")
.Include("Orders")
where ce.PersonID = personID
orderby ce.DateTimeContact descending
select ce)
.AsEnumerable()
.Select(e => new ContactEvent
{
ID = e.ID,
DateTimeContact = e.DateTimeContact,
Description = e.Description.Substring(0, 500),
Orders = e.Orders
});

Entitry Framework Add To Intersection Table

I have a User table and a Group table. Between these is a UserGroups intersection table to allow a user to belong to any number of groups.
The groups table is already populated with values.
How do I add a group to this user so that in the intersection table the relationship between the user and a group is created?
My Primary Keys auto increment.
My DB structure:
My EF structure:
(source: livefilestore.com)
Looks like i was missing the plot aboit.
the solutions is very simple.
Here is a little examle.
Thanks
using (UserEntities ctx = new UserEntities())
{
var group = (from g in ctx.Group
select g).FirstOrDefault();
User user = new User();
user.UserName = "Ian";
user.UserGroups.Add(new UserGroups { Group = group });
ctx.AddToUser(user);
ctx.SaveChanges();
}