Multiple join query in eSql - entity-framework

This is my first question in stackoverflow but really not the first time to get solution here. I am struggling with multiple join in entity framework 4. I have three tables (Accounts, Users and AccountUsers) that am finding difficult to query.
What I want is to get all the users for the provided accountId including the account creator. I can get all the account users with no problem but the hard side for me is getting the account creator since it's not added to AccountUsers table. below is a quick preview how the tables are related.
Accounts
AccountId
UserId (account creator)
...other columns
Users
UserId
...other columns
AccountUsers
AccountId
UserId
I would prefer the query to be esql, but Linq to Entities will do.
I trust you guys on stackoverflow, so I know this won't take long to get the 'Answer' mark.
Thanks for even reading.

If I'm reading your question right, you're not looking for a join so much as a union? I'm not sure about esql, but I'd think the following Linq query should work. Maybe it will get you going in the right direction (or I could be completely off-base or missing something):
var users = (from accountUser in db.AccountUsers
where accountUser.AccountId == myAccountId
select accountUser.UserId)
.ToList()
.Add((from account in db.Accounts
where account.AccountId == myAccountId
select account.UserId)
.Single());
To make it lazy loading, you could always make a method that makes use of foreach and yield return:
IEnumerable<int> GetAccountUsers(int AccountId)
{
//return the users
foreach(var userId in (from accountUser in db.AccountUsers
where accountUser.AccountId == myAccountId
select accountUser.UserId))
yield return userId;
//return the owner too
yield return (from account in db.Accounts
where account.AccountId == myAccountId
select account.UserId)
.Single();
}
Out of curiosity, though, why is the owner not also added to the AccountUsers table?

Related

How to filter via laravel relationship

Could someone help me if I can filter through laravel relationship in following scenario? I want to filter with the slip id / or customer_id/ or customer name.
public function search_index($query){
$slip = Slip::with('customer')
->where('slip_id',$query)
->orWhere('customer.id',$query)
->orWhere('customer.name',$query)->get();
}
Edit:
there are two classes: Slip and Customer. With the relations being slip belongs to customer and customer has many slips.
The slip contains other information including customer id and customer is retrieved using 'customer' relationship. Now I want to be able to find the slips by either entering customer name/id or slip id.
($query) may have one of those details
Slip::with('customer') returns details in following pattern:
[{slip:{id:1, ref:'abc', customer:{id:1,name:'Joe'}},}]
I want the query to return result in similar fashion too.
Thanks in advance
I haven't execute the code, but I pretty sure that this is gonna work.
$slip = Slip::query
->whereHas('customer', function(Builder $q) use ($query) {
return $q->where('id', $query) //Search by customer id
->orWhere('name', 'like', '%'.$query.'%'); //search by customer name similiarity
})
->orWhere('id', $query) //search by slip_id
->get();
This is not the best practice as I would suggest. It is recommended that you should break down the query in to 3 smaller functions/module, then get their intersect() as final result.

Is there a better way to perform a query like this in Entity Framework

I have a model called User and each user has a list of another model called Hobbies. I want to retrieve a User who has a hobby with a certain ID, is there anything better using Entity Framework than just retrieving all users then searching inside each user's hobbies list and match it with the hobby id, a pseudo code would look like the following
UserList = select all users from db
targetUser = null;
for User in UsersList:
for Hobby in User.HobbiesList:
if(Hobby.ID == currentHobby.ID)
{
targetUser = User;
}
First of all, EF won't automatically get all the linked entities, you need to explicitly Include everything you want to see in the end result.
As for the question, yes of course, you can use all the standard LINQ filters when working with EF. In your case
db.Userlist.Where(user => user.HobbiesList.Any(hobby => hobby.ID == currentHobby.ID))
Don't forget to Include(user => user.HobbiesList) if you want to see it in the results.

Using Linq with navigation properties

Trying to use navigation properties in a Linq query and not getting any results. Not sure why.
I'm using the standard Simple Membership tables in SQL Server with Entity Framework. So I've pulled the three tables, AspNetUsers, AspNetRoles and AspNetUserRoles into my model (See pic below)
YES, I KNOW I CAN USE THE ROLE/IDENTITY FUNCTIONS, I AM JUST USING THESE TABLES TO TRY OUT THIS LINQ QUERY, THESE TABLES WERE CONVENIENT TO USE
Anyway, my goal was to use the Navigation properties to get the roles for a given user. AspNetUserRoles does not get pulled into my model as an entity since it has no primary key, so this seemed the right way to go. I tried using the suggestion presented here:
Linq to entities navigation properties
The following linq query returns 0 results
var result = (from r in context.AspNetRoles
where r.AspNetUsers.Any(u => u.Id == UserId)
select r).ToList();
return result;
Thought maybe I needed to use the Include extension so I tried this, also returns 0 results
var result = (from r in context.AspNetRoles
where r.AspNetUsers.Any(u => u.Id == UserId)
select r).Include("AspNetUsers").ToList();
return result;
I know I'm doing something wrong with the line:
where r.AspNetUsers.Any(u => u.Id == UserId)
because if I remove it, I get results but not for a specific user, of course.
I'm trying to follow the advice given in one of the answers here:
Any ideas?
Thanks in advance!
If I understand correctly, you want to get all of a User's roles based on their Id.
Unless there is some information I am missing about your User model, then it is impossible to get this without accessing AspNetUserRoles.
If you can access that table, then this becomes really straightforward:
var result = AspNetUserRoles.Where(role => role.UserId == UserId)
.Select(userRole => AspNetRoles.First(role => role.Id == userRole.RoleId));
Or in query syntax:
var result = from userRole in AspNetUserRoles
where userRole.UserId == UserId
from role in AspNetRoles
where role.Id == userRole.RoleId
select role;

EF: One-to-many relationship - querying for a subset of the data

I am trying to fetch a collection of entities from a one-to-many relationship as an IQueryable so I can filter the data down before fetching this from the database.
To make it clear, consider the following example:
I currently have an entity "User" which has a collection of Pictures:
public virtual ICollection<Picture> Pictures{ get; set; }
The Picture entity may or may not belong to a User, and hence, doesnt have the User property in its definition.
A user may have thousands of pictures, but I would like to select the first 10 for example, ordered by Picture.Id. Is there a way to do this?
Maybe something along the lines like:
IQueryable<ICollection<Picture>> pictures = context.Users.Where(u=>u.UserId == userId).Select(c => c.Pictures)
Thanks!
The basic idea is to use the OrderBy and Take methods on the Pictures collection of the user. However, since you want to make sure that you only perform a single EntityFramework SQL query without loading the entire Pictures collection of a user, this needs to be expressed in a slightly more specific way.
Query syntax
var result = (from u in users
where u.Id == userId
from p in u.Pictures
orderby p.Id
select p).Take(10);
Method syntax
var result = context.Users
.Where(u => u.Id == 2)
.SelectMany(u => u.Pictures)
.OrderBy(p => p.Id)
.Take(10);
Note the call to SelectMany. It's important. Basically this adds up all the Pictures collections of all the selected users into one list and continues the query on this flattened meta-list. In theory this sounds like a pretty big operation, but in this case there should only be one user with a specific ID, so it really just continues with the selected user's Pictures collection. The generated SQL is a single, fast query:
Resulting SQL query (for both of the above)
SELECT TOP (10)
[Extent1].[User_Id] AS [User_Id],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Pictures] AS [Extent1]
WHERE ([Extent1].[User_Id] IS NOT NULL) AND (2 = [Extent1].[User_Id])
ORDER BY [Extent1].[Id] ASC

Entity Framework code first aspnet_Users mapping / joins

I was wondering with Entity Framework 4.1 code first how do you guys handle queries that involve an existing aspnet_Users table?
Basically I have a requirement for a query that involves the aspnet_Users so that I can return the username:
SELECT t.Prop1, u.Username
FROM Table1 t
INNER JOIN aspnet_User u ON t.UserId = u.UserId
Where t.Prop2 = true
Ideally in linq I would like:
from t in context.Table1
join u in context.aspnet_Users on t.UserId equals u.UserId
where t.Prop2 = true
But I'm not sure how to get aspnet_Users mapping to a class User? how do I make aspnet_Users part of my dbset ?
Any help would be appreciated, thanks in advance
Don't map aspnet_Users table or any other table related to aspnet. These tables have their own data access and their own logic for accessing. Mapping these tables will introduce code duplication, possible problems and breaks separation of concerns. If you need users for queries, create view with only needed information like id, user name, email and map the view. The point is that view will be read only, it will contain only allowed data and your application will not accidentally modify these data without using ASP.NET API.
First read Ladislav's answer. If you still want to go ahead : to do what you want would involve mapping the users and roles and members tables into the codefirst domain - which means writing a membership provider in code-first.
Luckily there is a project for that http://codefirstmembership.codeplex.com/ although its not a perfect implementation. The original is VB, look in the Discussion tab for my work on getting it running in c# MVC.
I'm working with the author on a better implementation that protects the membership data (password, last logged on date, all of the non-allowed data) but allow you to map and extend the user table. But its not ready yet!
You don't really need to use Entity Framework to access aspnet_membership provider accounts. You really just need to create an instance of the membership object, pass in a unique user identifier and a Boolean value indicating whether to update the LastActivityDate value for the user and the method returns a MembershipUser object populated with current values from the data source for the specified user.
You can then access the username by using the property of "Username".
Example:
private MembershipUser user =
Membership.GetUser(7578ec40-9e91-4458-b3d6-0a69dee82c6e, True);
Response.Write(user.UserName);
In case you have additional questions about MembershipProvider, you can read up on it on the MSDN website under the title of "Managing Users by Using Membership".
Hope this helps you some with your requirement.